diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..91abb11f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/cache-ospray.yml b/.github/workflows/cache-ospray.yml index c50078f8..5d36668f 100644 --- a/.github/workflows/cache-ospray.yml +++ b/.github/workflows/cache-ospray.yml @@ -55,18 +55,6 @@ jobs: if [[ ! -d "${{ inputs.cache-dir }}/ospray-${{ inputs.ospray-version }}" ]] then echo "Building " ${{ inputs.cache-dir }}/ospray-${{ inputs.ospray-version }} - if [ "${{ inputs.image }}" = "centos:7" ] - then - # *** CentOS 7 specific build *** - # CentOS 7, due to its extremely old glibc, requires everything built from source - echo "... CentOS 7 build" - module load intel/2022.1 - export CC=icx - export CXX=icpx - export CXXFLAGS="-fhonor-infinities -fhonor-nans" - export CFLAGS=$CXXFLAGS - fi - cmake -L -S ospray-${{ inputs.ospray-version }}/scripts/superbuild -B ospray-${{ inputs.ospray-version }}/build -DBUILD_OIDN=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_RKCOMMON_VERSION=${{ inputs.rkcommon-version }} -DINSTALL_IN_SEPARATE_DIRECTORIES=OFF cmake --build ospray-${{ inputs.ospray-version }}/build cp -r ospray-${{ inputs.ospray-version }} ${{ inputs.cache-dir }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bc86fde..77f30a49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: force-delete: true # guarantees .gitattributes are respected in working dir image: rockylinux:8.7 cmd: | - module load cmake/3.15.2 + module load cmake/3.25.3 module load intel/2023.0 export CC=icx export CXX=icpx @@ -85,34 +85,34 @@ jobs: ## Dev Build Jobs ## ## Linux - cache-ospray-centos7: + cache-ospray-rocky8-7: secrets: inherit uses: ./.github/workflows/cache-ospray.yml with: - image: centos:7 + image: rockylinux:8.7 ospray-version: devel rkcommon-version: devel - build-centos7-dev: - needs: cache-ospray-centos7 + build-rocky8-7-dev: + needs: cache-ospray-rocky8-7 uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: - image: centos:7 + image: rockylinux:8.7 cmd: | - module load cmake/3.15.2 + module load cmake/3.25.3 module load intel/2022.1 export CC=icx export CXX=icpx export CXXFLAGS="-fhonor-infinities -fhonor-nans" export CFLAGS=$CXXFLAGS - export CACHE_DIR=${{ needs.cache-ospray-centos7.outputs.cache-dir }} - export OSPRAY_VER=${{ needs.cache-ospray-centos7.outputs.ospray-version }} + export CACHE_DIR=${{ needs.cache-ospray-rocky8-7.outputs.cache-dir }} + export OSPRAY_VER=${{ needs.cache-ospray-rocky8-7.outputs.ospray-version }} export CMAKE_PREFIX_PATH=$CACHE_DIR/ospray-$OSPRAY_VER/build/install export TBB_ROOT=$CACHE_DIR/ospray-$OSPRAY_VER/build/tbb/src/tbb cmake -L -S . -B build -DENABLE_OPENIMAGEIO=OFF -DENABLE_OPENVDB=OFF -DENABLE_EXR=OFF cmake --build build -- -j`nproc` artifact-path: build - artifact-out: build-centos7-dev + artifact-out: build-rocky8-7-dev ## MacOS build-macos-clang-dev: @@ -142,12 +142,13 @@ jobs: cmake --build build-win-msvc16 --parallel $env:NUMBER_OF_PROCESSORS --config Release --target install ## Dev Test Jobs - test-run-centos7-dev: - needs: build-centos7-dev + test-run-rocky8-7-dev: + needs: build-rocky8-7-dev uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: - # Run the centos07-dev build on the ubuntu 18.04 image as a test, and because it has vncserver installed - image: ubuntu:18.04 + # Run the rocky8-7-dev build on the ubuntu 18.04 image as a test, and because it has vncserver installed + image: rockylinux:8.7-tgt-rebuild + pre-cmd: yum -y install tigervnc-server mesa-libGLU cmd: | module load intel/2023.0 build/ospStudio --verify_install @@ -155,19 +156,23 @@ jobs: export OSPRAY_VER=devel gitlab/run-dev.sh gitlab/run-dev-img-cmp.sh - artifact-in: build-centos7-dev - artifact-path: build/model-results - artifact-out: test-run-centos7-dev + artifact-in: build-rocky8-7-dev + artifact-path: build/model-results build/cert-tests/* + artifact-out: test-run-rocky8-7-dev artifact-on-failure: true - ### KW Jobs ### -# static-analysis: -# secrets: inherit -# uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/static_analysis.yml@tgt/ospray-studio -# with: -# project: ospray_studio -# image: ubuntu:18.04-tgt-klockwork -# prebuild: | -# cmake -L -S . -B build -DCMAKE_INSTALL_PREFIX=install -DENABLE_OPENIMAGEIO=OFF -DENABLE_OPENVDB=OFF -DENABLE_EXR=OFF -# build: cmake --build build - + ### Devel Coverity Job ### + static-analysis: + needs: cache-ospray-rocky8-7 + secrets: inherit + uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/static_analysis.yml@main + with: + project: OSPRay Studio + prebuild: > + module load cmake/3.25.3 && + export CACHE_DIR=${{ needs.cache-ospray-rocky8-7.outputs.cache-dir }} && + export OSPRAY_VER=${{ needs.cache-ospray-rocky8-7.outputs.ospray-version }} && + export CMAKE_PREFIX_PATH=$CACHE_DIR/ospray-$OSPRAY_VER/build/install/lib64/cmake/ospray-3.0.0 && + export TBB_ROOT=$CACHE_DIR/ospray-$OSPRAY_VER/build/tbb/src/tbb && + cmake -L -S . -B build -DENABLE_OPENIMAGEIO=OFF -DENABLE_OPENVDB=OFF -DENABLE_EXR=OFF + build: cmake --build build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 578e3a6d..03e56616 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,9 +26,10 @@ jobs: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: force-delete: true # guarantees .gitattributes are respected in working dir - image: rockylinux:8.7 +# image: rockylinux:8.7 + image: ubuntu:22.04 # temp, to use OSPRay v3.0.0 SYCL build cmd: | - module load cmake/3.15.2 + module load cmake/3.25.3 module load intel/2023.0 export CC=icx export CXX=icpx @@ -68,8 +69,10 @@ jobs: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: # Run the rockylinux 8.7 build on the ubuntu 18.04 image as a test, and because it has vncserver installed - image: ubuntu:18.04 - pre-cmd: apt install libglu1-mesa + #image: ubuntu:18.04 + #image: rockylinux:8.7-tgt-rebuild + image: ubuntu:22.04 # temp, to use OSPRay v3.0.0 SYCL build + #pre-cmd: yum -y install tigervnc-server mesa-libGLU cmd: | module load intel/2023.0 tar -xzf build/package/ospray_studio*.gz @@ -81,6 +84,21 @@ jobs: gitlab/run.sh artifact-in: release-linux + test-run-linux-gpu: + needs: release-linux + uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main + with: + image: ubuntu:22.04 + runs-on: '"dg2"' + options: --device=/dev/dri:/dev/dri + gfx-driver-version: linux-latest + cmd: | + module load intel/2023.0 + tar -xzf build/package/ospray_studio*.gz + export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray_studio-*/bin):$PATH + gitlab/run.sh --osp:load-modules=gpu --osp:device=gpu + artifact-in: release-linux + ## Windows ## test-release-windows-zip: needs: release-windows @@ -117,30 +135,31 @@ jobs: secrets: inherit uses: ./.github/workflows/cache-ospray.yml with: - image: centos:7 + image: rockylinux:8.7 ospray-version: devel rkcommon-version: devel + composition-analysis: + secrets: inherit + uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/composition_analysis.yml@main + static-analysis: needs: cache-ospray secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/static_analysis.yml@main with: - image: centos:7 - project: ospray_studio + coverity: true + image: rockylinux:8.7 + project: OSPRay Studio ignore-files: pysg.cpp - prebuild: | - module load cmake/3.15.2 - module load intel/2022.1 - export CC=icx - export CXX=icpx - export CXXFLAGS="-fhonor-infinities -fhonor-nans" - export CFLAGS=$CXXFLAGS - export CACHE_DIR=${{ needs.cache-ospray.outputs.cache-dir }} - export OSPRAY_VER=${{ needs.cache-ospray.outputs.ospray-version }} - export CMAKE_PREFIX_PATH=$CACHE_DIR/ospray-$OSPRAY_VER/build/install - export TBB_ROOT=$CACHE_DIR/ospray-$OSPRAY_VER/build/tbb/src/tbb - cmake -L -S . -B build -DENABLE_OPENIMAGEIO=OFF -DENABLE_OPENVDB=OFF -DENABLE_EXR=OFF + prebuild: > + module load cmake/3.25.3 && + export CACHE_DIR=${{ needs.cache-ospray.outputs.cache-dir }} && + export OSPRAY_VER=${{ needs.cache-ospray.outputs.ospray-version }} && + export CMAKE_PREFIX_PATH=$CACHE_DIR/ospray-$OSPRAY_VER/build/install && + export TBB_ROOT=$CACHE_DIR/ospray-$OSPRAY_VER/build/tbb/src/tbb && + cmake -L -S . -B build -DENABLE_OPENIMAGEIO=OFF -DENABLE_OPENVDB=OFF -DENABLE_EXR=OFF && + echo "Done: Configure OSPRay Studio" build: cmake --build build binary-analysis: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index ccd0be8d..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,380 +0,0 @@ -## Copyright 2009-2022 Intel Corporation -## SPDX-License-Identifier: Apache-2.0 - -variables: - GIT_SUBMODULE_STRATEGY: recursive - OSPRAY_VER: "2.10.0" - RKCOMMON_VER: "1.10.0" - PYTHON_VERSION: "3.9.7" - # PYTHON_ROOT_MACOS: "/NAS/packages/apps/python/$PYTHON_VERSION/macos" - PYTHON_ROOT_WINDOWS: "N:/packages/apps/python/$PYTHON_VERSION/windows" - -stages: - - build - - test - - release - - scan - - test-signing - -.centos7: - tags: [build, docker, modules] - image: $DOCKER_REGISTRY/centos:7 - before_script: - - module load python/$PYTHON_VERSION - - echo $Python3_ROOT - - ls $Python3_ROOT - -.centos7-test: - tags: [build, docker, modules] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod - before_script: - - module load python/$PYTHON_VERSION - - echo $Python3_ROOT - - ls $Python3_ROOT - -.ubuntu18.04: - tags: [build, docker, modules] - image: $DOCKER_REGISTRY/ubuntu:18.04-tgt-klockwork - -.ubuntu20.04: - tags: [build, docker] - image: $DOCKER_REGISTRY/clamav:ubuntu20.04 - -.macos: - tags: [osx, clang] - -.macos-sign: - tags: [osx, clang, sign] - -.windows: - tags: [win, msvc15] - before_script: - - $env:Python3_ROOT = $PYTHON_ROOT_WINDOWS - - echo $env:Python3_ROOT - - ls $env:Python3_ROOT - -.linux-build-artifacts: - artifacts: - name: ospray_studio - paths: - - build/ - -.macos-build-artifacts: - artifacts: - name: ospray-studio - paths: - - build-macos/ - -.windows-build-artifacts: - artifacts: - name: ospray-studio - paths: - - build-win/ - -.linux-release-artifacts: - artifacts: - name: ospray_studio - paths: - - build/package/ospray_studio* - -.macos-release-artifacts: - artifacts: - name: ospray_studio - paths: - - build-macos/package/ospray_studio* - only: - - master - - /^release-.*$/ - - devel - -.windows-release-artifacts: - artifacts: - name: ospray_studio - paths: - - build-win/package/ospray_studio* - only: - - master - - /^release-.*$/ - - devel - - #source-protex-scan: - # stage: scan - # image: amd64/openjdk:8 - # script: - # - gitlab/source-scan-protex.sh - # tags: [docker] - # needs: [] - # allow_failure: true - -######## -# These build phases will no longer work on current branches, due to non-release branch dependencies -######## - -build-centos7: - stage: build - extends: - - .centos7 - - .linux-build-artifacts - script: - - module load intel/2020.1 - - export CC=icc - - export CXX=icpc - - export CXXFLAGS="-static-intel -fPIC -D_GLIBCXX_USE_CXX11_ABI=0" - - gitlab/build.sh - -build-ubuntu18.04: - stage: build - extends: - - .ubuntu18.04 - - .linux-build-artifacts - script: - - gitlab/build.sh - only: - - master - - /^release-.*$/ - -build-macos-clang: - stage: build - extends: - - .macos - - .macos-build-artifacts - script: - - gitlab/macos.sh - only: - - master - - /^release-.*$/ - -build-windows-msvc15: - stage: build - extends: - - .windows - - .windows-build-artifacts - script: - - gitlab\win.ps1 - only: - - master - - /^release-.*$/ - -build-kw: - stage: build - extends: .centos7 - script: - - gitlab/build-kw.sh - artifacts: - paths: - - kw_tables - - klocwork/* - only: - - master - - /^release-.*$/ - -test-run-centos7: - stage: test - extends: .centos7-test - needs: [build-centos7] - script: - - build/install/bin/ospStudio --verify_install - -test-run-ubuntu18.04: - stage: test - extends: .ubuntu18.04 - needs: [build-ubuntu18.04] - script: - - gitlab/run.sh - only: - - master - - /^release-.*$/ - -test-kw: - stage: scan - extends: .centos7 - needs: [build-kw] - script: - - gitlab/kw-check-issues.sh - allow_failure: true - only: - - master - - /^release-.*$/ - -######## -# Transitional phases, only works against devel branch dependencies -######## - -build-ubuntu18.04-dev: - stage: build - extends: - - .ubuntu18.04 - - .linux-build-artifacts - script: - - gitlab/build-dev.sh - -build-macos-clang-dev: - stage: build - extends: - - .macos - - .macos-build-artifacts - script: - - gitlab/macos-dev.sh - -build-windows-msvc15-dev: - stage: build - extends: - - .windows - - .windows-build-artifacts - script: - - gitlab\win-dev.ps1 - -build-windows-icl: - stage: build - extends: - - .windows - script: - - mkdir build-win-icl - - cd build-win-icl - - cmake -L .. -G "Visual Studio 16 2019" -T "Intel C++ Compiler 19.2" -DCMAKE_INSTALL_PREFIX="install" - - cmake --build . --config Release --target install - artifacts: - paths: - - build-win-icl - when: manual - -build-kw-dev: - stage: build - extends: .ubuntu18.04 - script: - - gitlab/build-kw-dev.sh - artifacts: - paths: - - kw_tables - - klocwork/* - -test-kw-dev: - stage: scan - extends: .centos7 - needs: [build-kw-dev] - script: - - gitlab/kw-check-issues.sh - allow_failure: true - -kw-gen-report: - stage: scan - extends: .centos7 - needs: [build-kw-dev] - script: - - gitlab/kw-gen-report.sh - - gitlab/store-files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID klocwork "klocwork/report.log" - artifacts: - paths: - - klocwork/report.log - -test-run-ubuntu18.04-dev: - stage: test - extends: .ubuntu18.04 - needs: [build-ubuntu18.04-dev] - script: - - gitlab/run-dev.sh - -release-ubuntu18.04: - stage: release - extends: - - .ubuntu18.04 - - .linux-release-artifacts - dependencies: [] - script: - - gitlab/build.sh package - -release-centos7: - stage: release - extends: - - .centos7 - - .linux-release-artifacts - needs: [test-run-centos7] - dependencies: [] - script: - - module load intel/2020.1 - - export CC=icc - - export CXX=icpc - - export CXXFLAGS="-static-intel -fPIC -D_GLIBCXX_USE_CXX11_ABI=0" - - gitlab/build.sh package - -release-windows: - stage: release - extends: - - .windows - - .windows-release-artifacts - dependencies: [] - script: - - gitlab\win.ps1 package - - ;& $env:SIGN_FILE_WINDOWS $CI_PROJECT_DIR/build-win/package/ospray_studio*.msi - -test-release-windows-zip: - stage: test-signing - extends: - - .windows - - .windows-release-artifacts - needs: [release-windows] - script: - - Expand-Archive $CI_PROJECT_DIR/build-win/package/*.zip -DestinationPath . - - ;& $env:SIGN_FILE_WINDOWS -t (Get-ChildItem $CI_PROJECT_DIR\ospray_studio-*\bin\* | Select-Object -Expand FullName) - -test-release-windows-msi: - stage: test-signing - extends: - - .windows - - .windows-release-artifacts - needs: [release-windows] - script: - # XXX VERY IMPORTANT!!! msiexec returns immediately. Adding the pipe to Out-Null the simplest way to wait for completion - # XXX VERY IMPORTANT!!! never try to extract/install to the same TARGETDIR that the .msi file resides. It fails in a very opaque way. - - msiexec.exe /a (Get-ChildItem $CI_PROJECT_DIR/build-win/package/*.msi | Select-Object -Expand FullName) /qn TARGETDIR=$CI_PROJECT_DIR | Out-Null - - ;& $env:SIGN_FILE_WINDOWS -t $CI_PROJECT_DIR/build-win/package/*.msi (Get-ChildItem "$CI_PROJECT_DIR\Intel\OSPRay Studio v0\bin\*" | Select-Object -Expand FullName) - -release-macos: - stage: release - extends: - - .macos-sign - - .macos-release-artifacts - dependencies: [] - script: - - gitlab/macos.sh package - -test-release-macos: - stage: test-signing - extends: - - .macos-sign - - .macos-release-artifacts - needs: [release-macos] - script: - - unzip $CI_PROJECT_DIR/build-macos/package/*.zip - - $SIGN_FILE_MAC -t $CI_PROJECT_DIR/ospray_studio-*/bin/* $CI_PROJECT_DIR/ospray_studio-*/lib/*.dylib $CI_PROJECT_DIR/build-macos/package/*.pkg - -scan-bdba-bin: - stage: scan - extends: .centos7 - needs: [release-centos7, release-windows, release-macos] - script: - - gitlab/bdba.sh "build*/package/ospray_studio*" - - gitlab/store-files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID bdba "ospray_studio*.pdf" - - gitlab/store-files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID bdba "ospray_studio*.csv" - artifacts: - paths: - - ospray_studio*.pdf - - ospray_studio*.csv - only: - - master - - /^release-.*$/ - - devel - -av: - stage: scan - extends: .ubuntu20.04 - needs: [release-centos7, release-windows, release-macos] - script: - - freshclam | tee -a /tmp/av_scan.log - - clamscan -va --max-filesize=512M --max-scansize=2048M --alert-broken --alert-exceeds-max build*/package/ospray_studio* | tee -a /tmp/av_scan.log - - gitlab/store-files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID av /tmp/av_scan.log - only: - - master - - /^release-.*$/ - - devel - diff --git a/CHANGELOG.md b/CHANGELOG.md index ce8c827f..2d9ca72d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,61 @@ Version History --------------- +### Changes in OSPRay Studio v0.13.0 + +- Compatible with OSPRay release v3.0.0 + +- Features and Improvements + - OSPRay v3 Compatibility:<br> + - Intel Xe GPU beta support: launch Studio with parameters + `--osp:load-modules=gpu --osp:device=gpu` + - Add OSPRay v3 enum compatibility, tightened type-checking on all enum usage + - Add OSPRay v3 enum type comprehension to json for .sg files<br> + **(Note: This change will break existing .sg files. The most + common parameter is "intensityQuantity", which previously had + a subType of "uchar" and needs to change to + "OSPIntensityQuantity".)** + - Texture Formats: Support for .exr and .tiff image formats by + default though inclusion of tinyexr and tinydng 3rd party header-only + libraries. OpenImageIO is still available as a build option. + - Convert glTF light intensity from lux to watts. glTF specifies intensity + in lux, OSPRay in watts. Convert to watts for compatibility with glTF + exporters. + - Add default HDRI map, used when no other map is present. OSPRay used to + crash when removing HDRI map from light or when texture would fail to load. + Automatically switches to this default map now. + - Fix UI "pick focus distance" + - Left-Shift+left-mouse sets pick-point to center-of-screen, + center-of-arcball + - Left-Crl-Shift+left-mouse sets pick-point to focus distance without + moving center of arcball + - More intuitive behavior around Search All actions vs selected actions + - Transform editor now enables traversing selected node's parents + - Minor cleanup/refactor of GenerateImGuiWidgets + - Prevent filename widget collisions: + If there were multiple filename widgets visible, they would all + receive the file list returned by fileBrowser. + - Enable OpenImageDenoise in python bindings and python tutorial scripts + - Add ability to reload Assets rather than just instance + - Cameras loaded by assets now add to scene cameras rather than replacing + - Expose selectCamera to StudioContext, callable by plugins + - Enable parsing of general texture.transform in mtl files, was limited to + individual rotation, scale and translation +<br><br> + +- Cleanup and bug fixes: + - Prevent nullptr dereference on deleted importer assets + - Fix sporadic crash SearchWidget when search term had no match + - Use custom deleter for pre-C++17 compatability + - Resolve incorrect delete usage in Texture2D + - Fix addLight to update existing light parameters. + If addLight is called with an existing light, it was returning immediately. + It should update the light parameters with that of the new light. + - Be more careful about adding unique names in glTF importer. + When a node, light, or camera name is unclear a unique number is added to + the name. Importer was accidentally doing this twice or adding unique + number to already unique names. + ### Changes in OSPRay Studio v0.12.1 - Compatible with OSPRay release v2.12.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ba77965..819a3490 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.15) -project(ospray_studio VERSION 0.12.1 LANGUAGES CXX C) +project(ospray_studio VERSION 0.13.0 LANGUAGES CXX C) include(GNUInstallDirs) include(ProcessorCount) @@ -123,6 +123,14 @@ install(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt ${PROJECT_SOURCE_DIR}/third-party-programs.txt ${PROJECT_SOURCE_DIR}/third-party-programs-OSPRay.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-DPCPP.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-Embree.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-ISPC.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-OIDN.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-oneAPI-DPCPP.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-oneDNN.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-oneTBB.txt + ${PROJECT_SOURCE_DIR}/third-party-programs-OpenVKL.txt ${PROJECT_SOURCE_DIR}/CHANGELOG.md ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT apps diff --git a/README.md b/README.md index 2c3087a4..5bc08c33 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OSPRay Studio -This is release v0.12.1 of Intel® OSPRay Studio. It is released under the +This is release v0.13.0 of Intel® OSPRay Studio. It is released under the Apache 2.0 license. Visit [**OSPRay Studio**](http://www.ospray.org/ospray_studio) @@ -72,21 +72,21 @@ listed in OS-specific building process below. ### Required dependencies - [CMake](https://www.cmake.org) (v3.15+) and any C++14 compiler -- Intel [OSPRay](https://www.github.com/ospray/ospray) (v2.11.0) and its +- Intel [OSPRay](https://www.github.com/ospray/ospray) (v3.0.0) and its dependencies - OSPRay Studio builds on top of OSPRay. Instructions on building OSPRay are provided [here](http://www.ospray.org/downloads.html#building-and-finding-ospray). OSPRay and OSPRay Studio have the following common dependencies which Studio can hence leverage from an OSPRay build. - Intel oneAPI Rendering Toolkit common library - [rkcommon](https://www.github.com/ospray/rkcommon) (v1.11.0) + [rkcommon](https://www.github.com/ospray/rkcommon) (v1.12.0) - Intel [Threading Building Blocks](https://www.threadingbuildingblocks.org/) - OpenGL and [GLFW](https://www.glfw.org) (v3.3.8) - for the windowing environment ### Optional Dependencies -- Intel [Open Image Denoise](https://openimagedenoise.github.io) - (v1.4.3 or +- Intel [Open Image Denoise](https://openimagedenoise.github.io) - (v2.0.0 or newer) for denoising frames. To use with OSPRay Studio, OSPRay must be built with `-DBUILD_OIDN=ON` in CMake. - [OpenVDB](https://www.openvdb.org/) to support loading VDB formatted volume files. diff --git a/app/Batch.cpp b/app/Batch.cpp index 06931541..3ff2605b 100644 --- a/app/Batch.cpp +++ b/app/Batch.cpp @@ -250,7 +250,7 @@ void BatchContext::refreshRenderer() frame->createChild("renderer", "renderer_" + optRendererTypeStr); auto &r = frame->childAs<sg::Renderer>("renderer"); - r["pixelFilter"] = (int)optPF; + r["pixelFilter"] = optPF; r["backgroundColor"] = optBackGroundColor; r["pixelSamples"] = optSPP; r["varianceThreshold"] = optVariance; @@ -566,7 +566,7 @@ void BatchContext::updateCamera() } if (camera->hasChild("stereoMode")) - camera->child("stereoMode").setValue((int)optStereoMode); + camera->child("stereoMode").setValue((OSPStereoMode)optStereoMode); if (camera->hasChild("interpupillaryDistance")) camera->child("interpupillaryDistance").setValue(optInterpupillaryDistance); diff --git a/app/Batch.h b/app/Batch.h index dfe31916..a6b7eb33 100644 --- a/app/Batch.h +++ b/app/Batch.h @@ -27,6 +27,7 @@ class BatchContext : public StudioContext void refreshRenderer(); void refreshScene(bool resetCam) override; void updateCamera() override; + void selectCamera() override {}; void render(); virtual void renderFrame(); void renderAnimation(); diff --git a/app/CameraStack.h b/app/CameraStack.h index 232cec78..1a8c3a65 100644 --- a/app/CameraStack.h +++ b/app/CameraStack.h @@ -82,7 +82,7 @@ struct CameraStack CameraState slerp( const CameraState &from, const CameraState &to, float frac) const { - CameraState cs; + CameraState cs{}; cs.centerTranslation = lerp(frac, from.centerTranslation, to.centerTranslation); cs.translation = lerp(frac, from.translation, to.translation); diff --git a/app/GUIContext.cpp b/app/GUIContext.cpp index e0526804..5753b541 100644 --- a/app/GUIContext.cpp +++ b/app/GUIContext.cpp @@ -43,6 +43,9 @@ GUIContext::GUIContext(StudioCommon &_common) if (frame->hasChild("framebuffer")) framebuffer = frame->child("framebuffer").nodeAs<FrameBuffer>(); defaultSize = _common.defaultSize; + + // Define "default" camera in cameras list + g_sceneCameras["default"] = frame->child("camera").nodeAs<Camera>(); } GUIContext::~GUIContext() @@ -208,6 +211,7 @@ void GUIContext::changeToDefaultCamera() } } + cameraIdx = 0; // reset global-context cameraIndex frame->remove("camera"); frame->add(defaultCamera); frame->commit(); @@ -233,7 +237,7 @@ void GUIContext::refreshRenderer() frame->createChild("renderer", "renderer_" + optRendererTypeStr); auto &r = frame->childAs<Renderer>("renderer"); - r["pixelFilter"] = (int)optPF; + r["pixelFilter"] = optPF; r["backgroundColor"] = optBackGroundColor; r["pixelSamples"] = optSPP; r["varianceThreshold"] = optVariance; @@ -264,7 +268,7 @@ void GUIContext::saveRendererParams() auto &r = frame->childAs<Renderer>("renderer"); optRendererTypeStr = r["type"].valueAs<std::string>(); - optPF = (OSPPixelFilterTypes)r["pixelFilter"].valueAs<int>(); + optPF = r["pixelFilter"].valueAs<OSPPixelFilterType>(); optBackGroundColor = r["backgroundColor"].valueAs<rgba>(); optSPP = r["pixelSamples"].valueAs<int>(); optVariance = r["varianceThreshold"].valueAs<float>(); @@ -372,14 +376,15 @@ void GUIContext::importFiles(NodePtr world) try { rkcommon::FileName fileName(file); - // XXX: handling loading a scene here for now + // XXX: handling loading a scene here for now, it requires the entire + // context. if (fileName.ext() == "sg") { importScene(shared_from_this(), fileName); sgScene = true; } else { std::cout << "Importing: " << file << std::endl; - auto importer = getImporter(world, file); + auto importer = getImporter(world, file, optReloadAssets); if (importer) { auto vp = importer->getVolumeParams(); if (volumeParams->children().size() > 0 && vp) { @@ -445,11 +450,12 @@ void GUIContext::importFiles(NodePtr world) // Initializes time range for newly imported models mainWindow->animationWidget->init(); - // XXX this shouldn't completely replace g_sceneCameras, but add to it. - if (sgFileCameras) - g_sceneCameras = *sgFileCameras; - else if (cameras) - g_sceneCameras = *cameras; + const auto &newCameras = sgFileCameras ? *sgFileCameras : *cameras; + if (!newCameras.empty()) { + for (const auto &camera : newCameras) + if (camera.second) + g_sceneCameras[camera.first] = camera.second; + } } void GUIContext::saveCurrentFrame() @@ -642,6 +648,7 @@ void GUIContext::selectCamera() if (whichCamera < (int)g_sceneCameras.size()) { auto &newCamera = g_sceneCameras.at_index(whichCamera); g_selectedSceneCamera = newCamera.second; + g_selectedSceneCamera->child("cameraId").setValue(whichCamera); auto hasParents = g_selectedSceneCamera->parents().size(); frame->remove("camera"); frame->add(g_selectedSceneCamera); diff --git a/app/GUIContext.h b/app/GUIContext.h index e9dfd555..d35d4d58 100644 --- a/app/GUIContext.h +++ b/app/GUIContext.h @@ -84,7 +84,7 @@ class GUIContext : public StudioContext // windows and main menu builder related functions void selectBuffer(OSPFrameBufferChannel whichBuffer, bool invert = false); - void selectCamera(); + void selectCamera() override; void createNewCamera(const std::string newType); void createIsoSurface( int currentVolume, std::vector<ospray::sg::NodePtr> &volumes); diff --git a/app/MainMenuBuilder.h b/app/MainMenuBuilder.h index 40f52b5f..aca3ec44 100644 --- a/app/MainMenuBuilder.h +++ b/app/MainMenuBuilder.h @@ -82,8 +82,15 @@ void MainMenuBuilder::buildMainMenuFile() if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("Import ...", nullptr)) - showImportFileBrowser = true; + + ImGui::Checkbox("ReloadAssets", &ctx->optReloadAssets); + sg::showTooltip("ReloadAssets will reload asset file contents, rather than creating an instance."); + ImGui::Checkbox("ResetCamera", &ctx->optResetCameraOnLoad); + sg::showTooltip( + "Resets camera position to new world size when loading assets,\n" + "otherwise camera parameters remain untouched."); + if (ImGui::BeginMenu("Demo Scene")) { for (size_t i = 0; i < g_scenes.size(); ++i) { if (ImGui::MenuItem(g_scenes[i].c_str(), nullptr)) { @@ -169,10 +176,11 @@ void MainMenuBuilder::buildMainMenuFile() if (fileBrowser(ctx->filesToImport, "Select Import File(s) - ", true)) { showImportFileBrowser = false; // do not reset camera when loading a scene file - bool resetCam = true; + bool resetCam = ctx->optResetCameraOnLoad; for (auto &fn : ctx->filesToImport) if (rkcommon::FileName(fn).ext() == "sg") resetCam = false; + ctx->changeToDefaultCamera(); ctx->refreshScene(resetCam); } } diff --git a/app/MainWindow.cpp b/app/MainWindow.cpp index 9d7b3c4b..a4f075bd 100644 --- a/app/MainWindow.cpp +++ b/app/MainWindow.cpp @@ -433,7 +433,7 @@ void MainWindow::pickCenterOfRotation(float x, float y) vec3f worldPosition; x = clamp(x / windowSize.x, 0.f, 1.f); y = 1.f - clamp(y / windowSize.y, 0.f, 1.f); - if (ctx->resHasHit(x, y, worldPosition)) + if (ctx->resHasHit(x, y, worldPosition)) { if (!(glfwGetKey(glfwWindow, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)) { // Constraining rotation around the up works pretty well. arcballCamera->constrainedRotate(vec2f(0.5f, 0.5f), vec2f(x, y), 1); @@ -441,8 +441,10 @@ void MainWindow::pickCenterOfRotation(float x, float y) arcballCamera->setZoomLevel(preFPVZoom + arcballCamera->getZoomLevel()); preFPVZoom = 0.f; arcballCamera->setCenter(vec3f(worldPosition)); - ctx->updateCamera(); } + // Update camera + ctx->updateCamera(); + } } void MainWindow::keyboardMotion() diff --git a/app/PluginManager.cpp b/app/PluginManager.cpp index 5e70d4a7..c4aae0cb 100644 --- a/app/PluginManager.cpp +++ b/app/PluginManager.cpp @@ -6,45 +6,50 @@ #include "sg/PluginCore.h" #include <iterator> +#include <memory> + +PluginManager::PluginManager() + : plugins(std::make_shared<std::vector<LoadedPlugin>>()) +{} void PluginManager::loadPlugin(const std::string &name) { void *plugin = ospray::sg::loadPluginCore(name); if (plugin != nullptr) { auto pluginInstance = - std::unique_ptr<Plugin>(static_cast<Plugin *>(plugin)); + std::unique_ptr<Plugin>(static_cast<Plugin *>(plugin)); addPlugin(std::move(pluginInstance)); } } void PluginManager::addPlugin(std::unique_ptr<Plugin> plugin) { - plugins.emplace_back(LoadedPlugin{std::move(plugin), true}); + plugins->emplace_back(LoadedPlugin{std::move(plugin), true}); } void PluginManager::removePlugin(const std::string &name) { - plugins.erase(std::remove_if(plugins.begin(), plugins.end(), [&](auto &p) { + plugins->erase(std::remove_if(plugins->begin(), plugins->end(), [&](auto &p) { return p.instance->name() == name; })); } void PluginManager::removeAllPlugins() { - plugins.clear(); + plugins->clear(); } bool PluginManager::hasPlugin(const std::string &pluginName) { - for (auto &p : plugins) + for (auto &p : *plugins) if (p.instance->name() == pluginName) return true; return false; } -LoadedPlugin* PluginManager::getPlugin(std::string &pluginName) +LoadedPlugin *PluginManager::getPlugin(std::string &pluginName) { - for (auto &l : plugins) + for (auto &l : *plugins) if (l.instance->name() == pluginName) return &l; @@ -54,8 +59,8 @@ LoadedPlugin* PluginManager::getPlugin(std::string &pluginName) void PluginManager::main( std::shared_ptr<StudioContext> ctx, PanelList *allPanels) const { - if (!plugins.empty()) - for (auto &plugin : plugins) { + if (!plugins->empty()) + for (auto &plugin : *plugins) { plugin.instance->mainMethod(ctx); if (!plugin.instance->panels.empty() && allPanels) { auto &pluginPanels = plugin.instance->panels; @@ -70,8 +75,8 @@ void PluginManager::mainPlugin(std::shared_ptr<StudioContext> ctx, std::string &pluginName, PanelList *allPanels) const { - if (!plugins.empty()) - for (auto &plugin : plugins) { + if (!plugins->empty()) + for (auto &plugin : *plugins) { if (plugin.instance->name() == pluginName) { plugin.instance->mainMethod(ctx); if (!plugin.instance->panels.empty() && allPanels) { diff --git a/app/PluginManager.h b/app/PluginManager.h index 42b27306..ba0c259a 100644 --- a/app/PluginManager.h +++ b/app/PluginManager.h @@ -5,17 +5,17 @@ #include "Plugin.h" - // Helper types // - struct LoadedPlugin - { - std::unique_ptr<ospray::Plugin> instance; - bool active{true}; - }; +// Helper types // +struct LoadedPlugin +{ + std::unique_ptr<ospray::Plugin> instance; + bool active{true}; +}; class PluginManager { - public: - PluginManager() = default; + public: + PluginManager(); ~PluginManager() = default; void loadPlugin(const std::string &name); @@ -23,14 +23,18 @@ class PluginManager void removeAllPlugins(); // TODO: add functions to get a fresh set of panels, activate/deactivate, etc. - void main( - std::shared_ptr<StudioContext> ctx, ospray::PanelList *allPanels = nullptr) const; + void main(std::shared_ptr<StudioContext> ctx, + ospray::PanelList *allPanels = nullptr) const; void mainPlugin(std::shared_ptr<StudioContext> ctx, - std::string &pluginName, - ospray::PanelList *allPanels = nullptr) const; + std::string &pluginName, + ospray::PanelList *allPanels = nullptr) const; bool hasPlugin(const std::string &pluginName); LoadedPlugin *getPlugin(std::string &pluginName); + inline std::shared_ptr<std::vector<LoadedPlugin>> getPlugins() + { + return plugins; + } private: // Helper functions // @@ -39,5 +43,5 @@ class PluginManager // Data // - std::vector<LoadedPlugin> plugins; + std::shared_ptr<std::vector<LoadedPlugin>> plugins; }; diff --git a/app/WindowsBuilder.h b/app/WindowsBuilder.h index 17ce523d..1ca95c30 100644 --- a/app/WindowsBuilder.h +++ b/app/WindowsBuilder.h @@ -550,9 +550,6 @@ void WindowsBuilder::buildWindowLightEditor() static SearchWidget searchWidget(types, types, sg::TreeState::ALLCLOSED); searchWidget.addSearchBarUI(*lightsManager); - searchWidget.addCustomAction("enable all", showSearch, showSearch); - searchWidget.addCustomAction("disable all", hideSearch, hideSearch, true); - searchWidget.addSearchResultsUI(*lightsManager); auto selected = searchWidget.getSelected(); if (selected) { @@ -560,14 +557,19 @@ void WindowsBuilder::buildWindowLightEditor() selected->traverse<sg::SetParamByNode>(NT::LIGHT, "enable", enable); }; - ImGui::Text("Selected "); - ImGui::SameLine(); if (ImGui::Button("enable")) toggleSelected(true); ImGui::SameLine(); if (ImGui::Button("disable")) toggleSelected(false); + } else { + searchWidget.addCustomAction("enable all", showSearch, showSearch); + searchWidget.addCustomAction("disable all", hideSearch, hideSearch, true); + } + searchWidget.addSearchResultsUI(*lightsManager); + + if (selected) { GenerateWidget(*selected); if (ImGui::Button("remove")) { @@ -664,18 +666,21 @@ void WindowsBuilder::buildWindowCameraEditor() } auto frameCameraId = ctx->frame->child("camera").child("cameraId").valueAs<int>(); - ctx->whichCamera = frameCameraId; - auto &items = ctx->g_sceneCameras; + if (frameCameraId >= items.size()) + frameCameraId = items.size() - 1; + // Only present selector UI if more than one camera - if (!items.empty() && ImGui::BeginCombo("sceneCameras##whichCamera", - items.at_index(ctx->whichCamera).first.c_str())) { + if (!items.empty() + && ImGui::BeginCombo("sceneCameras##whichCamera", + items.at_index(frameCameraId).first.c_str())) { for (int i = 0; i < items.size(); ++i) { - const bool isSelected = (ctx->whichCamera == i); + const bool isSelected = (frameCameraId == i); if (ImGui::Selectable(items.at_index(i).first.c_str(), isSelected)) { ctx->whichCamera = i; ctx->selectCamera(); + break; } if (isSelected) { ImGui::SetItemDefaultFocus(); @@ -966,9 +971,6 @@ void WindowsBuilder::buildWindowTransformEditor() auto &warudo = ctx->frame->child("world"); static SearchWidget searchWidget(searchTypes, displayTypes); searchWidget.addSearchBarUI(warudo); - searchWidget.addCustomAction("show all", showSearch, showDisplay); - searchWidget.addCustomAction("hide all", hideSearch, hideDisplay, true); - searchWidget.addSearchResultsUI(warudo); auto selected = searchWidget.getSelected(); if (selected) { @@ -982,14 +984,23 @@ void WindowsBuilder::buildWindowTransformEditor() } }; - ImGui::Text("Selected "); - ImGui::SameLine(); if (ImGui::Button("show")) toggleSelected(true); ImGui::SameLine(); if (ImGui::Button("hide")) toggleSelected(false); + } else { + searchWidget.addCustomAction("show all", showSearch, showDisplay); + searchWidget.addCustomAction("hide all", hideSearch, hideDisplay, true); + } + + searchWidget.addSearchResultsUI(warudo); + if (selected) { + if (ImGui::Button("select parent")) + if (!selected->parents().empty() && selected->parents().front()) + searchWidget.setSelected(*selected->parents().front()); + sg::showTooltip("Move selection up one level to parent node.\n"); GenerateWidget(*selected); } @@ -1100,8 +1111,8 @@ void WindowsBuilder::viewCameraPath(bool showCameraPath) path->createChildData("vertex.position_radius", pathVertices); path->createChildData("vertex.color", colors); path->createChildData("index", indexes); - path->createChild("type", "uchar", (unsigned char)OSP_ROUND); - path->createChild("basis", "uchar", (unsigned char)OSP_CATMULL_ROM); + path->createChild("type", "OSPCurveType", OSP_ROUND); + path->createChild("basis", "OSPCurveBasis", OSP_CATMULL_ROM); path->createChildData("material", mID); path->child("material").setSGOnly(); diff --git a/app/ospStudio.cpp b/app/ospStudio.cpp index 52d4e30f..bc5c385a 100644 --- a/app/ospStudio.cpp +++ b/app/ospStudio.cpp @@ -17,6 +17,9 @@ using namespace ospray; using rkcommon::removeArgs; +// Disables the main try/except used to report errors, makes debug easier +#define EXCEPTION_GUARD + void StudioCommon::splitPluginArguments() { int original_argc = argc; @@ -62,6 +65,11 @@ void StudioContext::addToCommandLine(std::shared_ptr<CLI::App> app) filesToImport, "The list of files to import" ); + app->add_option( + "reload assets", + optReloadAssets, + "reload asset file contents, rather than creating an instance" + ); app->add_option( "--renderer", optRendererTypeStr, @@ -194,7 +202,7 @@ void StudioContext::addToCommandLine(std::shared_ptr<CLI::App> app) app->add_option_function<OSPDataType>( "--voxelType", [&](const OSPDataType &voxelType) { - volumeParams->createChild("voxelType", "int", (int)voxelType); + volumeParams->createChild("voxelType", "OSPDataType", voxelType); }, "Set the voxel type for imported volumes" )->transform(CLI::CheckedTransformer(sg::volumeVoxelType)); @@ -393,7 +401,10 @@ int main(int argc, const char *argv[]) // This scope contains all OSPRay API calls. It enforces cleanly calling all // destructors before calling ospShutdown() - try { +#if defined(EXCEPTION_GUARD) + try +#endif + { std::shared_ptr<StudioContext> context = nullptr; // XXX Modes should be module loaded, statically linked causes @@ -422,11 +433,14 @@ int main(int argc, const char *argv[]) else std::cerr << "Could not create a valid context. Stopping." << std::endl; - } catch (const std::exception &e) { + } +#if defined(EXCEPTION_GUARD) + catch (const std::exception &e) { std::cerr << "ospStudio internal error: '" << e.what() << "'!" << std::endl; } catch (...) { std::cerr << "ospStudio unknown internal error!" << std::endl; } +#endif ospShutdown(); diff --git a/app/ospStudio.h b/app/ospStudio.h index 6eff7190..0518dfc7 100644 --- a/app/ospStudio.h +++ b/app/ospStudio.h @@ -131,6 +131,7 @@ class StudioContext : public std::enable_shared_from_this<StudioContext> virtual void importFiles(sg::NodePtr world) = 0; virtual void refreshScene(bool resetCam) = 0; virtual void updateCamera() = 0; + virtual void selectCamera() = 0; virtual void updateCameraIndices(uint32_t idx); virtual void loadCamJson() = 0; @@ -155,13 +156,15 @@ class StudioContext : public std::enable_shared_from_this<StudioContext> StudioMode mode; + bool optReloadAssets{false}; + bool optResetCameraOnLoad{true}; std::string optRendererTypeStr{"pathtracer"}; std::string optCameraTypeStr{"perspective"}; bool optVerboseImporter{false}; int optSPP{32}; float optVariance{0.f}; // varianceThreshold sg::rgba optBackGroundColor{vec3f(0.0f), 1.f}; // default to black - OSPPixelFilterTypes optPF{OSP_PIXELFILTER_GAUSS}; + OSPPixelFilterType optPF{OSP_PIXELFILTER_GAUSS}; bool optDenoiser{false}; bool optDenoiseFinalFrame{false}; bool optGridEnable{false}; diff --git a/app/widgets/GenerateImGuiWidgets.h b/app/widgets/GenerateImGuiWidgets.h index 7e0636f8..d96ec3ba 100644 --- a/app/widgets/GenerateImGuiWidgets.h +++ b/app/widgets/GenerateImGuiWidgets.h @@ -81,66 +81,10 @@ inline bool generateWidget_bool(const std::string &title, Node &node) return false; } -inline bool generateWidget_uchar(const std::string &title, Node &node) -{ - // ImGui has no native char types - int i = node.valueAs<uint8_t>(); - - if (node.readOnly()) { - ImGui::Text("%s", (node.name() + ": " + std::to_string(i)).c_str()); - nodeTooltip(node); - return false; - } - - if (node.hasMinMax()) { - const int min = node.minAs<uint8_t>(); - const int max = node.maxAs<uint8_t>(); - if (ImGui::SliderInt(title.c_str(), &i, min, max)) { - node.setValue(uint8_t(i)); - return true; - } - } else { - if (ImGui::DragInt(title.c_str(), &i, 1)) { - node.setValue(uint8_t(i)); - return true; - } - } - - nodeTooltip(node); - return false; -} - +template <typename T> inline bool generateWidget_int(const std::string &title, Node &node) { - int i = node.valueAs<int>(); - - if (node.readOnly()) { - ImGui::Text("%s", (node.name() + ": " + std::to_string(i)).c_str()); - nodeTooltip(node); - return false; - } - - if (node.hasMinMax()) { - const int min = node.minAs<int>(); - const int max = node.maxAs<int>(); - if (ImGui::SliderInt(title.c_str(), &i, min, max)) { - node.setValue(i); - return true; - } - } else { - if (ImGui::DragInt(title.c_str(), &i, 1)) { - node.setValue(i); - return true; - } - } - - nodeTooltip(node); - return false; -} - -inline bool generateWidget_long(const std::string &title, Node &node) -{ - int i = static_cast<int>(node.valueAs<long>()); + int i = static_cast<int>(node.valueAs<T>()); if (node.readOnly()) { ImGui::Text("%s", (node.name() + ": " + std::to_string(i)).c_str()); @@ -149,15 +93,15 @@ inline bool generateWidget_long(const std::string &title, Node &node) } if (node.hasMinMax()) { - const long min = node.minAs<long>(); - const long max = node.maxAs<long>(); + const int min = node.minAs<T>(); + const int max = node.maxAs<T>(); if (ImGui::SliderInt(title.c_str(), &i, min, max)) { - node.setValue(static_cast<long>(i)); + node.setValue(static_cast<T>(i)); return true; } } else { if (ImGui::DragInt(title.c_str(), &i, 1)) { - node.setValue(static_cast<long>(i)); + node.setValue(static_cast<T>(i)); return true; } } @@ -578,11 +522,14 @@ inline bool generateWidget_filename(const std::string &title, Node &node) } static bool showFileBrowser = false; + static std::string active{""}; // This field won't be typed into. ImGui::InputTextWithHint( node.name().c_str(), (char *)f.c_str(), (char *)f.c_str(), 0); - if (ImGui::IsItemClicked()) + if (ImGui::IsItemClicked()) { showFileBrowser = true; + active = title; + } if (f != "") { ImGui::SameLine(); @@ -593,10 +540,11 @@ inline bool generateWidget_filename(const std::string &title, Node &node) } // Leave the fileBrowser open until file is selected - if (showFileBrowser) { + if (showFileBrowser && title == active) { ospray_studio::FileList fileList = {}; if (ospray_studio::fileBrowser(fileList, "Select file")) { showFileBrowser = false; + active = ""; if (!fileList.empty()) { node.setValue(std::string(fileList[0])); return true; @@ -611,9 +559,10 @@ inline bool generateWidget_filename(const std::string &title, Node &node) using WidgetGenerator = bool (*)(const std::string &, Node &); static std::map<std::string, WidgetGenerator> widgetGenerators = { {"bool", generateWidget_bool}, - {"uchar", generateWidget_uchar}, - {"int", generateWidget_int}, - {"long", generateWidget_long}, + {"uchar", generateWidget_int<uint8_t>}, + {"int", generateWidget_int<int>}, + {"uint32_t", generateWidget_int<uint32_t>}, + {"long", generateWidget_int<long>}, {"float", generateWidget_float}, {"vec2i", generateWidget_vec2i}, {"vec2f", generateWidget_vec2f}, @@ -629,6 +578,28 @@ static std::map<std::string, WidgetGenerator> widgetGenerators = { {"quaternionf", generateWidget_quaternionf}, {"string", generateWidget_string}, {"filename", generateWidget_filename}, + + // OSPRay Enum types + {"OSPAMRMethod", generateWidget_int<OSPAMRMethod>}, + {"OSPCurveBasis", generateWidget_int<OSPCurveBasis>}, + {"OSPCurveType", generateWidget_int<OSPCurveType>}, + {"OSPDataType", generateWidget_int<OSPDataType>}, + {"OSPDeviceProperty", generateWidget_int<OSPDeviceProperty>}, + {"OSPError", generateWidget_int<OSPError>}, + {"OSPFrameBufferChannel", generateWidget_int<OSPFrameBufferChannel>}, + {"OSPFrameBufferFormat", generateWidget_int<OSPFrameBufferFormat>}, + {"OSPIntensityQuantity", generateWidget_int<OSPIntensityQuantity>}, + {"OSPLogLevel", generateWidget_int<OSPLogLevel>}, + {"OSPPixelFilterType", generateWidget_int<OSPPixelFilterType>}, + {"OSPShutterType", generateWidget_int<OSPShutterType>}, + {"OSPStereoMode", generateWidget_int<OSPStereoMode>}, + {"OSPSubdivisionMode", generateWidget_int<OSPSubdivisionMode>}, + {"OSPSyncEvent", generateWidget_int<OSPSyncEvent>}, + {"OSPTextureFilter", generateWidget_int<OSPTextureFilter>}, + {"OSPTextureFormat", generateWidget_int<OSPTextureFormat>}, + {"OSPUnstructuredCellType", generateWidget_int<OSPUnstructuredCellType>}, + {"OSPVolumeFilter", generateWidget_int<OSPVolumeFilter>}, + {"OSPVolumeFormat", generateWidget_int<OSPVolumeFormat>} }; // Inlined definitions //////////////////////////////////////////////////// diff --git a/app/widgets/SearchWidget.cpp b/app/widgets/SearchWidget.cpp index 47d907cb..0047f4c6 100644 --- a/app/widgets/SearchWidget.cpp +++ b/app/widgets/SearchWidget.cpp @@ -14,10 +14,13 @@ void SearchWidget::clear() searched = false; searchResults.clear(); allDisplayItems.clear(); // force generation of non-searched items + resultsCount = 0; searchTerm[0] = '\0'; selectedResultName = ""; - numPages = 0; + numPages = 1; currentPage = 1; + numItemsPerPage = std::atoi(numItemsOpt[numItemsInd]); + childHeight = (numItemsPerPage + 1) * ImGui::GetTextLineHeightWithSpacing(); } void SearchWidget::search(NR root) @@ -30,6 +33,7 @@ void SearchWidget::search(NR root) } searched = true; + currentPage = 1; searchResults.clear(); // Search the entire hierarchy of passed-in root node for nodes of specific @@ -82,6 +86,7 @@ void SearchWidget::addSearchResultsUI(NR root) // Create a vector of all unsearched items matching displayTypes if (allDisplayItems.empty() || root.children().size() != rootSize) { rootSize = root.children().size(); + allDisplayItems.clear(); // force generation of non-searched items for (const auto child : root.children()) { if (isOneOf(child.second->type(), displayTypes)) allDisplayItems.push_back(child.second); @@ -89,13 +94,16 @@ void SearchWidget::addSearchResultsUI(NR root) calculatePages(); } - ImGui::BeginChild( - "Results", ImVec2(0, childHeight), true, ImGuiWindowFlags_HorizontalScrollbar); - for (int i = (currentPage - 1) * numItemsPerPage; + ImGui::BeginChild("Results", + ImVec2(0, childHeight), + true, + ImGuiWindowFlags_HorizontalScrollbar); + currentPage = std::max(currentPage, 1); + auto &itemVector = searched ? searchResults : allDisplayItems; + for (unsigned i = (currentPage - 1) * numItemsPerPage; i < std::min(resultsCount, currentPage * numItemsPerPage); i++) { - const auto itemVector = searched ? searchResults : allDisplayItems; - const auto node = itemVector.at(i).lock(); + const auto node = i < itemVector.size() ? itemVector.at(i).lock() : nullptr; auto itemTypes = searched ? searchTypes : displayTypes; if (node && isOneOf(node->type(), itemTypes)) { const bool isSelected = (selectedIndex == i); diff --git a/app/widgets/SearchWidget.h b/app/widgets/SearchWidget.h index 5a218f26..8fbcf51a 100644 --- a/app/widgets/SearchWidget.h +++ b/app/widgets/SearchWidget.h @@ -72,8 +72,11 @@ class SearchWidget { // Set the new selected result selectedResultName = selectedNode.name(); - selectedResultParent = - selectedNode.parents().front()->nodeAs<ospray::sg::Node>(); + // In case the user has selected upward to the root node + selectedResultParent = selectedNode.parents().empty() + ? lastRoot->nodeAs<ospray::sg::Node>() + : selectedNode.parents().front()->nodeAs<ospray::sg::Node>(); + selectedIndex = -1; allDisplayItems.clear(); } @@ -90,7 +93,7 @@ class SearchWidget int numItemsInd{0}; int numItemsPerPage{10}; float childHeight{numItemsPerPage * ImGui::GetTextLineHeightWithSpacing()}; - int numPages{0}; + int numPages{1}; int currentPage{1}; std::string paginateLabel{""}; @@ -100,9 +103,12 @@ class SearchWidget { resultsCount = int(searched ? searchResults.size() : allDisplayItems.size()); - numPages = std::max(resultsCount / numItemsPerPage, 1); + numPages = + std::max(int(std::ceil(float(resultsCount) / numItemsPerPage)), 1); paginateLabel = "of " + std::to_string(numPages) + "##currentPage"; currentPage = std::min(currentPage, numPages); + childHeight = std::min(childHeight, (resultsCount + 1) + * ImGui::GetTextLineHeightWithSpacing()); }; // Number of children under the root matching type in displayTypes diff --git a/cmake/benchmark.cmake b/cmake/benchmark.cmake index 73e7a620..38714254 100644 --- a/cmake/benchmark.cmake +++ b/cmake/benchmark.cmake @@ -6,7 +6,7 @@ ## if(NOT DEFINED BENCHMARK_VERSION) - set(BENCHMARK_VERSION 1.5.5) + set(BENCHMARK_VERSION 1.8.3) endif() ## @@ -27,6 +27,8 @@ if(NOT "${benchmark_FOUND}") set(BENCHMARK_ENABLE_TESTING OFF) set(BENCHMARK_ENABLE_GTEST_TESTS OFF) + set(BENCHMARK_ENABLE_INSTALL OFF) + set(BENCHMARK_INSTALL_DOCS OFF) FetchContent_Declare( benchmark URL "https://github.com/google/benchmark/archive/refs/tags/v${BENCHMARK_VERSION}.${_BENCHMARK_ARCHIVE_EXT}" diff --git a/cmake/ospray.cmake b/cmake/ospray.cmake index fb91cca4..32528845 100644 --- a/cmake/ospray.cmake +++ b/cmake/ospray.cmake @@ -10,7 +10,7 @@ message(STATUS "Looking for OSPRay...") find_package(ospray QUIET) if(NOT DEFINED OSPRAY_VERSION) - set(OSPRAY_VERSION 2.12.0) + set(OSPRAY_VERSION 3.0.0) endif() if(ospray_FOUND) @@ -19,6 +19,7 @@ else() ## Download and build if not found if(WIN32) set(_ARCHIVE_EXT "windows.zip") + set(OSPRAY_TAG ".sycl") elseif(APPLE) set(_ARCHIVE_EXT "macosx.zip") else() @@ -26,7 +27,7 @@ else() endif() if(NOT DEFINED OSPRAY_URL) - set(OSPRAY_URL "https://github.com/ospray/ospray/releases/download/v${OSPRAY_VERSION}/ospray-${OSPRAY_VERSION}.x86_64.${_ARCHIVE_EXT}") + set(OSPRAY_URL "https://github.com/ospray/ospray/releases/download/v${OSPRAY_VERSION}/ospray-${OSPRAY_VERSION}${OSPRAY_TAG}.x86_64.${_ARCHIVE_EXT}") endif() include(FetchContent) diff --git a/cmake/rkcommon.cmake b/cmake/rkcommon.cmake index 875f6990..6a5e24ca 100644 --- a/cmake/rkcommon.cmake +++ b/cmake/rkcommon.cmake @@ -13,7 +13,7 @@ message(STATUS "Looking for rkcommon...") find_package(rkcommon QUIET) if(NOT DEFINED RKCOMMON_VERSION) - set(RKCOMMON_VERSION 1.11.0) + set(RKCOMMON_VERSION 1.12.0) endif() if(rkcommon_FOUND) diff --git a/cmake/tbb.cmake b/cmake/tbb.cmake index e2a0f124..1270ed10 100644 --- a/cmake/tbb.cmake +++ b/cmake/tbb.cmake @@ -6,7 +6,7 @@ if(TBB_FOUND) endif() if(NOT DEFINED TBB_VERSION) - set(TBB_VERSION 2021.9.0) + set(TBB_VERSION 2021.10.0) endif() option(FORCE_TBB_VERSION "Force CMake to find ${TBB_VERSION} (typically for compatibility with pre-built OSPRay)" OFF) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 26613c18..4f6310a6 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -7,5 +7,7 @@ add_subdirectory(imGuIZMO.quat) add_subdirectory(tiny_obj_loader) add_subdirectory(tiny_gltf) add_subdirectory(stb_image) +add_subdirectory(tiny_exr) +add_subdirectory(tiny_dng) add_subdirectory(json) add_subdirectory(cli11) diff --git a/external/tiny_dng/CMakeLists.txt b/external/tiny_dng/CMakeLists.txt new file mode 100644 index 00000000..306df294 --- /dev/null +++ b/external/tiny_dng/CMakeLists.txt @@ -0,0 +1,14 @@ +## Copyright 2023 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +add_library(tiny_dng STATIC tiny_dng_impl.cpp) + +target_include_directories(tiny_dng +PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> +) + +target_link_libraries(tiny_dng +PRIVATE + stb_image +) diff --git a/external/tiny_dng/tiny_dng_impl.cpp b/external/tiny_dng/tiny_dng_impl.cpp new file mode 100644 index 00000000..9086cb6c --- /dev/null +++ b/external/tiny_dng/tiny_dng_impl.cpp @@ -0,0 +1,8 @@ +// Copyright 2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +// Define TINY_DNG_LOADER_IMPLEMENTATION and STB_IMAGE_IMPLEMENTATION in only one *.cc +#define TINY_DNG_LOADER_USE_THREAD +//#define TINY_DNG_LOADER_NO_STB_IMAGE_INCLUDE +#define TINY_DNG_LOADER_IMPLEMENTATION +#include "tiny_dng_loader.h" diff --git a/external/tiny_dng/tiny_dng_loader.h b/external/tiny_dng/tiny_dng_loader.h new file mode 100644 index 00000000..78571bc4 --- /dev/null +++ b/external/tiny_dng/tiny_dng_loader.h @@ -0,0 +1,6038 @@ +// +// TinyDNGLoader, single header only DNG/TIFF loader. +// + +/* +The MIT License (MIT) + +Copyright (c) 2016 - Present, Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#ifndef TINY_DNG_LOADER_H_ +#define TINY_DNG_LOADER_H_ + +// @note { +// https://www.adobe.com/content/dam/Adobe/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf +// } + +#include <cstdint> +#include <string> +#include <vector> + +namespace tinydng { + +// TODO: Deal with out-of-memory error +// e.g. limit maximum images in one DNG/TIFF file +const size_t kMaxImages = 10240; + +// TODO: Set max allowed size in loader option. +const size_t kMaxImageSizeInMB = 64*1024; // 64 GB + +// Avoid stack-overflow of recursive Sub IFD parsing. +const uint32_t kMaxRecursiveIFDParse = 1024; + +typedef enum { + LIGHTSOURCE_UNKNOWN = 0, + LIGHTSOURCE_DAYLIGHT = 1, + LIGHTSOURCE_FLUORESCENT = 2, + LIGHTSOURCE_TUNGSTEN = 3, + LIGHTSOURCE_FLASH = 4, + LIGHTSOURCE_FINE_WEATHER = 9, + LIGHTSOURCE_CLOUDY_WEATHER = 10, + LIGHTSOURCE_SHADE = 11, + LIGHTSOURCE_DAYLIGHT_FLUORESCENT = 12, + LIGHTSOURCE_DAY_WHITE_FLUORESCENT = 13, + LIGHTSOURCE_COOL_WHITE_FLUORESCENT = 14, + LIGHTSOURCE_WHITE_FLUORESCENT = 15, + LIGHTSOURCE_STANDARD_LIGHT_A = 17, + LIGHTSOURCE_STANDARD_LIGHT_B = 18, + LIGHTSOURCE_STANDARD_LIGHT_C = 19, + LIGHTSOURCE_D55 = 20, + LIGHTSOURCE_D65 = 21, + LIGHTSOURCE_D75 = 22, + LIGHTSOURCE_D50 = 23, + LIGHTSOURCE_ISO_STUDIO_TUNGSTEN = 24, + LIGHTSOURCE_OTHER_LIGHT_SOURCE = 255 +} LightSource; + +typedef enum { + COMPRESSION_NONE = 1, + COMPRESSION_LZW = 5, // LZW + COMPRESSION_OLD_JPEG = 6, // JPEG or lossless JPEG + COMPRESSION_NEW_JPEG = 7, // Usually lossles JPEG, may be JPEG + COMPRESSION_ZIP = 8, // ZIP + COMPRESSION_LOSSY = 34892, // Lossy JPEG(usually 8-bit standard JPEG) + COMPRESSION_NEF = 34713 // NIKON RAW +} Compression; + +typedef enum { + TYPE_NOTYPE = 0, + TYPE_BYTE = 1, + TYPE_ASCII = 2, // null-terminated string + TYPE_SHORT = 3, + TYPE_LONG = 4, + TYPE_RATIONAL = 5, // 64-bit unsigned fraction + TYPE_SBYTE = 6, + TYPE_UNDEFINED = 7, // 8-bit untyped data */ + TYPE_SSHORT = 8, + TYPE_SLONG = 9, + TYPE_SRATIONAL = 10, // 64-bit signed fraction + TYPE_FLOAT = 11, + TYPE_DOUBLE = 12, + TYPE_IFD = 13, // 32-bit unsigned integer (offset) + TYPE_LONG8 = 16, // BigTIFF 64-bit unsigned + TYPE_SLONG8 = 17, // BigTIFF 64-bit signed + TYPE_IFD8 = 18 // BigTIFF 64-bit unsigned integer (offset) +} DataType; + +typedef enum { + SAMPLEFORMAT_UINT = 1, + SAMPLEFORMAT_INT = 2, + SAMPLEFORMAT_IEEEFP = 3, // floating point + SAMPLEFORMAT_VOID = 4, + SAMPLEFORMAT_COMPLEXINT = 5, + SAMPLEFORMAT_COMPLEXIEEEFP = 6 +} SampleFormat; + +struct FieldInfo { + int tag; + short read_count; + short write_count; + DataType type; + unsigned short bit; + unsigned char ok_to_change; + unsigned char pass_count; + std::string name; + + FieldInfo() + : tag(0), + read_count(-1), + write_count(-1), + type(TYPE_NOTYPE), + bit(0), + ok_to_change(0), + pass_count(0) {} +}; + +struct FieldData { + int tag; + DataType type; + std::string name; + std::vector<unsigned char> data; + + FieldData() : tag(0), type(TYPE_NOTYPE) {} +}; + +struct GainMap { + unsigned int idx; // 1, 2 or 3: OpCodeListN. 0 = invalid + unsigned int top, left, bottom, right; + unsigned int plane, planes; + unsigned int row_pitch, col_pitch; + unsigned int map_points_v, map_points_h; + int _pad0; + double map_spacing_v, map_spacing_h; + double map_origin_v, map_origin_h; + unsigned int map_planes; + + int _pad1; + std::vector<float> pixels; // size = map_points_v * map_points_h * map_planes + + GainMap() : idx(0) { + } +}; + +struct DNGImage { + int black_level[4]; // for each spp(up to 4) + int white_level[4]; // for each spp(up to 4) + int version; // DNG version + + int samples_per_pixel; + int rows_per_strip; + + int bits_per_sample_original; // BitsPerSample in stored file. + int bits_per_sample; // Bits per sample after reading(decoding) DNG image. + + char cfa_plane_color[4]; // 0:red, 1:green, 2:blue, 3:cyan, 4:magenta, + // 5:yellow, 6:white + int cfa_pattern[2][2]; // @fixme { Support non 2x2 CFA pattern. } + short cfa_pattern_dim; + short _pad_cfa_patern_dim; + int cfa_layout; + int active_area[4]; // top, left, bottom, right + bool has_active_area; + unsigned char pad_has_active_area[3]; + + int tile_width; + int tile_length; + unsigned int tile_offset; + unsigned int tile_byte_count; // (compressed) size + + int pad0; + double analog_balance[3]; + bool has_analog_balance; + unsigned char pad1[7]; + + double as_shot_neutral[3]; + int pad3; + bool has_as_shot_neutral; + unsigned char pad4[7]; + + int pad5; + double color_matrix1[3][3]; + double color_matrix2[3][3]; + + double forward_matrix1[3][3]; + double forward_matrix2[3][3]; + + double camera_calibration1[3][3]; + double camera_calibration2[3][3]; + + LightSource calibration_illuminant1; + LightSource calibration_illuminant2; + + int width; + int height; + int compression; + unsigned int offset; + short orientation; + short _pad0; + int strip_byte_count; + int jpeg_byte_count; + short planar_configuration; // 1: chunky, 2: planar + short predictor; // tag 317. 1 = no prediction, 2 = horizontal differencing, + // 3 = floating point horizontal differencing + + SampleFormat sample_format; + + // For an image with multiple strips. + int strips_per_image; + std::vector<unsigned int> strip_byte_counts; + std::vector<unsigned int> strip_offsets; + + // CR2(Canon RAW) specific + unsigned short cr2_slices[3]; + unsigned short pad_c; + + // Apple ProRAW + std::string semantic_name; + + // GainMap + std::vector<GainMap> opcodelist1_gainmap; + std::vector<GainMap> opcodelist2_gainmap; + std::vector<GainMap> opcodelist3_gainmap; + + std::vector<unsigned char> + data; // Decoded pixel data(len = spp * width * height * bps / 8) + + // Custom fields + std::vector<FieldData> custom_fields; +}; + +/// +/// Loads DNG image and store it to `images` +/// +/// If DNG contains multiple images(e.g. full-res image + thumnail image), +/// The function creates `DNGImage` data strucure for each images. +/// +/// @param[in] filename DNG filename. +/// @param[in] custom_fields List of custom fields to parse(optional. can pass +/// empty array). +/// @param[out] images Loaded DNG images. +/// @param[out] warn Warning message. +/// @param[out] err Error message. +/// +/// @return true upon success. +/// @return false upon failure and store error message into `err`. +/// +bool LoadDNG(const char* filename, std::vector<FieldInfo>& custom_fields, + std::vector<DNGImage>* images, std::string* warn, + std::string* err); + +/// +/// Check if a file is DNG(TIFF) or not. +/// Extra message will be stored `msg`. +/// +bool IsDNG(const char* filename, std::string* msg); + +/// +/// A variant of `LoadDNG` which loads DNG image from memory. +/// Up to 2GB DNG data. +/// +bool LoadDNGFromMemory(const char* mem, unsigned int size, + std::vector<FieldInfo>& custom_fields, + std::vector<DNGImage>* images, std::string* warn, + std::string* err); + +/// +/// A variant of `IsDNG` which checks if a data is DNG image. +/// +bool IsDNGFromMemory(const char* mem, unsigned int size, std::string* msg); + +} // namespace tinydng + +#ifdef TINY_DNG_LOADER_IMPLEMENTATION + +#if defined(_WIN32) +#if defined(__MINGW32__) +#include <windows.h> // wchar apis +#else +#include <Windows.h> +#endif +#endif + +#include <stdint.h> // for lj92 + +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <iterator> +#include <map> +#include <sstream> +#include <limits> + +#if defined(TINY_DNG_LOADER_NO_STDIO) +#else +#include <cstdio> +#include <cassert> +#include <iostream> +#endif + +// #include <iostream> // dbg + +#ifdef TINY_DNG_LOADER_PROFILING +// Requires C++11 feature +#include <chrono> +#endif + +#if __cplusplus > 199911L + +#ifdef TINY_DNG_LOADER_USE_THREAD +#include <atomic> +#include <thread> +#include <mutex> +#endif + +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" +#endif + +// #define TINY_DNG_LOADER_DEBUG +#ifdef TINY_DNG_LOADER_DEBUG +#define TINY_DNG_DPRINTF(...) printf(__VA_ARGS__) +#else +#define TINY_DNG_DPRINTF(...) +#endif + +#if 0 // DBG + +#define TINY_DNG_DEBUG_SAVEIMAGE +#if defined(TINY_DNG_DEBUG_SAVEIMAGE) +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "examples/common/stb_image_write.h" +#endif + +#endif + +// msg: std::string +// err: std::string* +#define TINY_DNG_ERROR_AND_RETURN(msg, err) \ + do { \ + if (err) { \ + std::ostringstream ss_e; \ + ss_e << "[TinyDNG error]: " << __func__ << "():" << __LINE__ << " " ; \ + ss_e << msg << "\n"; \ + (*err) += ss_e.str(); \ + } \ + return false; \ + } while (0) + +// check cond, set error message and return false when cond failed. +#define TINY_DNG_CHECK_AND_RETURN(cond, msg, err) \ + do { \ + if (!(cond)) { \ + if (err) { \ + std::ostringstream ss_e; \ + ss_e << "[TinyDNG error]: " << __func__ << "():" << __LINE__ << " " ; \ + ss_e << msg << "\n"; \ + (*err) += ss_e.str(); \ + } \ + return false; \ + } \ + } while (0) + +#define TINY_DNG_CHECK_AND_RETURN_C(cond, retcode) \ + do { \ + if (!(cond)) { \ + return (retcode); \ + } \ + } while (0) + + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wall" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif + + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#pragma warning(disable : 4334) +#pragma warning(disable : 4244) +#endif + +#ifdef TINY_DNG_LOADER_ENABLE_ZIP +#ifndef TINY_DNG_LOADER_USE_SYSTEM_ZLIB +#include "miniz.h" +#endif +#endif + +#if defined(TINY_DNG_LOADER_NO_STB_IMAGE_INCLUDE) +#else + +// STB image to decode jpeg image. +// Assume STB_IMAGE_IMPLEMENTATION is defined elsewhere +#include "stb_image.h" +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace tinydng { + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-extensions" +#pragma clang diagnostic ignored "-Wold-style-cast" +#pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wcast-align" +#pragma clang diagnostic ignored "-Wconditional-uninitialized" +#pragma clang diagnostic ignored "-Wunused-function" +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" +#pragma clang diagnostic ignored "-Wdouble-promotion" +#pragma clang diagnostic ignored "-Wimplicit-fallthrough" +#if __has_warning("-Wcomma") +#pragma clang diagnostic ignored "-Wcomma" +#endif +#if __has_warning("-Wcast-qual") +#pragma clang diagnostic ignored "-Wcast-qual" +#endif +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#pragma warning(disable : 4334) +#pragma warning(disable : 4244) +#endif + +namespace { +// Begin liblj92, Lossless JPEG decode/encoder ------------------------------ +// +// With fixes: https://github.com/ilia3101/MLV-App/pull/151 + +/* +lj92.c +(c) Andrew Baldwin 2014 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +enum LJ92_ERRORS { + LJ92_ERROR_NONE = 0, + LJ92_ERROR_CORRUPT = -1, + LJ92_ERROR_NO_MEMORY = -2, + LJ92_ERROR_BAD_HANDLE = -3, + LJ92_ERROR_TOO_WIDE = -4 +}; + +typedef struct _ljp* lj92; + +/* Parse a lossless JPEG (1992) structure returning + * - a handle that can be used to decode the data + * - width/height/bitdepth of the data + * Returns status code. + * If status == LJ92_ERROR_NONE, handle must be closed with lj92_close + */ +int lj92_open(lj92* lj, // Return handle here + const uint8_t* data, int datalen, // The encoded data + int* width, int* height, + int* bitdepth); // Width, height and bitdepth + +/* Release a decoder object */ +void lj92_close(lj92 lj); + +/* + * Decode previously opened lossless JPEG (1992) into a 2D tile of memory + * Starting at target, write writeLength 16bit values, then skip 16bit + * skipLength value before writing again + * If linearize is not NULL, use table at linearize to convert data values from + * output value to target value + * Data is only correct if LJ92_ERROR_NONE is returned + */ +int lj92_decode( + lj92 lj, uint16_t* target, int writeLength, + int skipLength, // The image is written to target as a tile + uint16_t* linearize, + int linearizeLength); // If not null, linearize the data using this table + +#if 0 +/* + * Encode a grayscale image supplied as 16bit values within the given bitdepth + * Read from tile in the image + * Apply delinearization if given + * Return the encoded lossless JPEG stream + */ +int lj92_encode(uint16_t* image, int width, int height, int bitdepth, + int readLength, int skipLength, uint16_t* delinearize, + int delinearizeLength, uint8_t** encoded, + int* encodedLength); +#endif + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +//#define SLOW_HUFF +//#define LJ92_DEBUG + +#define LJ92_MAX_COMPONENTS (16) + +typedef struct _ljp { + u8* data; + u8* dataend; + int datalen; + int scanstart; + int ix; + int x; // Width + int y; // Height + int bits; // Bit depth + int components; // Components(Nf) + int writelen; // Write rows this long + int skiplen; // Skip this many values after each row + u16* linearize; // Linearization table + int linlen; + int sssshist[16]; + +// Huffman table - only one supported, and probably needed +#ifdef SLOW_HUFF + // NOTE: Huffman table for each components is not supported for SLOW_HUFF code + // path. + int* maxcode; + int* mincode; + int* valptr; + u8* huffval; + int* huffsize; + int* huffcode; +#else + // Huffman table for each components + u16* hufflut[LJ92_MAX_COMPONENTS]; + int huffbits[LJ92_MAX_COMPONENTS]; + int num_huff_idx; +#endif + // Parse state + int cnt; + u32 b; + u16* image; + u16* rowcache; + u16* outrow[2]; +} ljp; + +static int find(ljp* self) { + int ix = self->ix; + u8* data = self->data; + while (data[ix] != 0xFF && ix < (self->datalen - 1)) { + ix += 1; + } + ix += 2; + if (ix >= self->datalen) { + // TINY_DNG_DPRINTF("idx = %d, datalen = %\d\n", ix, self->datalen); + return -1; + } + self->ix = ix; + // TINY_DNG_DPRINTF("ix = %d, data = %d\n", ix, data[ix - 1]); + return data[ix - 1]; +} + +// swap endian +#define BEH(ptr) ((((int)(*&ptr)) << 8) | (*(&ptr + 1))) + +static int parseHuff(ljp* self) { + int ret = LJ92_ERROR_CORRUPT; + u8* huffhead = + &self->data + [self->ix]; // xstruct.unpack('>HB16B',self.data[self.ix:self.ix+19]) + u8* bits = &huffhead[2]; + bits[0] = 0; // Because table starts from 1 + int hufflen = BEH(huffhead[0]); + if ((self->ix + hufflen) >= self->datalen) return ret; +#ifdef SLOW_HUFF + u8* huffval = calloc(hufflen - 19, sizeof(u8)); + if (huffval == NULL) return LJ92_ERROR_NO_MEMORY; + self->huffval = huffval; + for (int hix = 0; hix < (hufflen - 19); hix++) { + huffval[hix] = self->data[self->ix + 19 + hix]; +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("huffval[%d]=%d\n", hix, huffval[hix]); +#endif + } + self->ix += hufflen; + // Generate huffman table + int k = 0; + int i = 1; + int j = 1; + int huffsize_needed = 1; + // First calculate how long huffsize needs to be + while (i <= 16) { + while (j <= bits[i]) { + huffsize_needed++; + k = k + 1; + j = j + 1; + } + i = i + 1; + j = 1; + } + // Now allocate and do it + int* huffsize = calloc(huffsize_needed, sizeof(int)); + if (huffsize == NULL) return LJ92_ERROR_NO_MEMORY; + self->huffsize = huffsize; + k = 0; + i = 1; + j = 1; + // First calculate how long huffsize needs to be + int hsix = 0; + while (i <= 16) { + while (j <= bits[i]) { + huffsize[hsix++] = i; + k = k + 1; + j = j + 1; + } + i = i + 1; + j = 1; + } + huffsize[hsix++] = 0; + + // Calculate the size of huffcode array + int huffcode_needed = 0; + k = 0; + int code = 0; + int si = huffsize[0]; + while (1) { + while (huffsize[k] == si) { + huffcode_needed++; + code = code + 1; + k = k + 1; + } + if (huffsize[k] == 0) break; + while (huffsize[k] != si) { + code = code << 1; + si = si + 1; + } + } + // Now fill it + int* huffcode = calloc(huffcode_needed, sizeof(int)); + if (huffcode == NULL) return LJ92_ERROR_NO_MEMORY; + self->huffcode = huffcode; + int hcix = 0; + k = 0; + code = 0; + si = huffsize[0]; + while (1) { + while (huffsize[k] == si) { + huffcode[hcix++] = code; + code = code + 1; + k = k + 1; + } + if (huffsize[k] == 0) break; + while (huffsize[k] != si) { + code = code << 1; + si = si + 1; + } + } + + i = 0; + j = 0; + + int* maxcode = calloc(17, sizeof(int)); + if (maxcode == NULL) return LJ92_ERROR_NO_MEMORY; + self->maxcode = maxcode; + int* mincode = calloc(17, sizeof(int)); + if (mincode == NULL) return LJ92_ERROR_NO_MEMORY; + self->mincode = mincode; + int* valptr = calloc(17, sizeof(int)); + if (valptr == NULL) return LJ92_ERROR_NO_MEMORY; + self->valptr = valptr; + + while (1) { + while (1) { + i++; + if (i > 16) break; + if (bits[i] != 0) break; + maxcode[i] = -1; + } + if (i > 16) break; + valptr[i] = j; + mincode[i] = huffcode[j]; + j = j + bits[i] - 1; + maxcode[i] = huffcode[j]; + j++; + } + free(huffsize); + self->huffsize = NULL; + free(huffcode); + self->huffcode = NULL; + ret = LJ92_ERROR_NONE; +#else + /* Calculate huffman direct lut */ + // How many bits in the table - find highest entry + u8* huffvals = &self->data[self->ix + 19]; + int maxbits = 16; + while (maxbits > 0) { + if (bits[maxbits]) break; + maxbits--; + } + self->huffbits[self->num_huff_idx] = maxbits; + TINY_DNG_DPRINTF("huffbuts[%d] = %d\n", self->num_huff_idx, maxbits); + + /* Now fill the lut */ + u16* hufflut = (u16*)malloc((1 << maxbits) * sizeof(u16)); + // TINY_DNG_DPRINTF("maxbits = %d\n", maxbits); + if (hufflut == NULL) return LJ92_ERROR_NO_MEMORY; + self->hufflut[self->num_huff_idx] = hufflut; + int i = 0; + int hv = 0; + int rv = 0; + int vl = 0; // i + int hcode; + int bitsused = 1; +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("%04x:%x:%d:%x\n", i, huffvals[hv], bitsused, + 1 << (maxbits - bitsused)); +#endif + while (i < 1 << maxbits) { + if (bitsused > maxbits) { + break; // Done. Should never get here! + } + if (vl >= bits[bitsused]) { + bitsused++; + vl = 0; + continue; + } + if (rv == 1 << (maxbits - bitsused)) { + rv = 0; + vl++; + hv++; +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("%04x:%x:%d:%x\n", i, huffvals[hv], bitsused, + 1 << (maxbits - bitsused)); +#endif + continue; + } + hcode = huffvals[hv]; + hufflut[i] = hcode << 8 | bitsused; + TINY_DNG_DPRINTF("idx[%d] hufflut[%d] = %d(bitsused = %d, hcode = %d\n",self->num_huff_idx, i, hufflut[i], bitsused,hcode); + i++; + rv++; + } + ret = LJ92_ERROR_NONE; +#endif + self->num_huff_idx++; + + return ret; +} + +static int parseSof3(ljp* self) { + if (self->ix + 6 >= self->datalen) return LJ92_ERROR_CORRUPT; + self->y = BEH(self->data[self->ix + 3]); + self->x = BEH(self->data[self->ix + 5]); + self->bits = self->data[self->ix + 2]; + self->components = self->data[self->ix + 7]; + self->ix += BEH(self->data[self->ix]); + + if ((self->components >= 1) && (self->components < 6)) { + // ok + } else { + // Invalid number of components. + return LJ92_ERROR_CORRUPT; + } + //TINY_DNG_ASSERT(self->components >= 1 && self->components < 6, + // "Invalid number of components."); + + return LJ92_ERROR_NONE; +} + +static int parseBlock(ljp* self, int marker) { + (void)marker; + self->ix += BEH(self->data[self->ix]); + if (self->ix >= self->datalen) { + TINY_DNG_DPRINTF("parseBlock: ix %d, datalen %d\n", self->ix, + self->datalen); + return LJ92_ERROR_CORRUPT; + } + return LJ92_ERROR_NONE; +} + +#ifdef SLOW_HUFF +static int nextbit(ljp* self) { + u32 b = self->b; + if (self->cnt == 0) { + u8* data = &self->data[self->ix]; + u32 next = *data++; + b = next; + if (next == 0xff) { + data++; + self->ix++; + } + self->ix++; + self->cnt = 8; + } + int bit = b >> 7; + self->cnt--; + self->b = (b << 1) & 0xFF; + return bit; +} + +static int decode(ljp* self) { + int i = 1; + int code = nextbit(self); + while (code > self->maxcode[i]) { + i++; + code = (code << 1) + nextbit(self); + } + int j = self->valptr[i]; + j = j + code - self->mincode[i]; + int value = self->huffval[j]; + return value; +} + +static int receive(ljp* self, int ssss) { + int i = 0; + int v = 0; + while (i != ssss) { + i++; + v = (v << 1) + nextbit(self); + } + return v; +} + +static int extend(ljp* self, int v, int t) { + int vt = 1 << (t - 1); + if (v < vt) { + vt = (-1 << t) + 1; + v = v + vt; + } + return v; +} +#endif + +inline static int nextdiff(ljp* self, int component_idx, int Px, int *errcode) { + (void)Px; +#ifdef SLOW_HUFF + int t = decode(self); + int diff = receive(self, t); + diff = extend(self, diff, t); +// TINY_DNG_DPRINTF("%d %d %d %x\n",Px+diff,Px,diff,t);//,index,usedbits); +#else + if (component_idx <= self->num_huff_idx) { + // OK + } else { + // "Invalid huff index."); + if (errcode) { + (*errcode) = LJ92_ERROR_CORRUPT; + } + return 0; + } + + //TINY_DNG_ASSERT(component_idx <= self->num_huff_idx, "Invalid huff index."); + u32 b = self->b; + int cnt = self->cnt; + int huffbits = self->huffbits[component_idx]; + int ix = self->ix; + int next; + while (cnt < huffbits) { + next = *(u16*)&self->data[ix]; + int one = next & 0xFF; + int two = next >> 8; + b = (b << 16) | (one << 8) | two; + cnt += 16; + ix += 2; + if (one == 0xFF) { + // TINY_DNG_DPRINTF("%x %x %x %x %d\n",one,two,b,b>>8,cnt); + b >>= 8; + cnt -= 8; + } else if (two == 0xFF) + ix++; + } + int index = b >> (cnt - huffbits); + // TINY_DNG_DPRINTF("component_idx = %d / %d, index = %d\n", component_idx, + // self->components, index); + + u16 ssssused = self->hufflut[component_idx][index]; + int usedbits = ssssused & 0xFF; + int t = ssssused >> 8; + self->sssshist[t]++; + cnt -= usedbits; + int keepbitsmask = (1 << cnt) - 1; + b &= keepbitsmask; + while (cnt < t) { + next = *(u16*)&self->data[ix]; + int one = next & 0xFF; + int two = next >> 8; + b = (b << 16) | (one << 8) | two; + cnt += 16; + ix += 2; + if (one == 0xFF) { + b >>= 8; + cnt -= 8; + } else if (two == 0xFF) + ix++; + } + cnt -= t; + int diff = b >> cnt; + int vt = 1 << (t - 1); + if (diff < vt) { + vt = (-1 << t) + 1; + diff += vt; + } + keepbitsmask = (1 << cnt) - 1; + self->b = b & keepbitsmask; + self->cnt = cnt; + self->ix = ix; +// TINY_DNG_DPRINTF("%d %d\n",t,diff); +// TINY_DNG_DPRINTF("%d %d %d %x %x %d\n",Px+diff,Px,diff,t,index,usedbits); +#ifdef LJ92_DEBUG +#endif +#endif + return diff; +} + +#if 0 // not used +static int parsePred6(ljp* self) { + // TODO: Consider self->components + TINY_DNG_DPRINTF("parsePred6\n"); + int ret = LJ92_ERROR_CORRUPT; + self->ix = self->scanstart; + // int compcount = self->data[self->ix+2]; + self->ix += BEH(self->data[self->ix]); + self->cnt = 0; + self->b = 0; + int write = self->writelen; + // Now need to decode huffman coded values + int c = 0; + int pixels = self->y * self->x; + u16* out = self->image; + u16* temprow; + u16* thisrow = self->outrow[0]; + u16* lastrow = self->outrow[1]; + + // First pixel predicted from base value + int diff; + int Px; + int col = 0; + int row = 0; + int left = 0; + int linear; + if (self->num_huff_idx <= self->components) { + // ok + } else { + //TINY_DNG_ASSERT(self->num_huff_idx <= self->components, + // "Invalid number of huff indices."); + return LJ92_ERROR_CORRUPT; + } + int errcode = LJ92_ERROR_NONE; + // First pixel + diff = nextdiff(self, self->num_huff_idx - 1, + 0, &errcode); // FIXME(syoyo): Is using (self->num_huff_idx-1) correct? + if (errcode != LJ92_ERROR_NONE) { + return errcode; + } + + Px = 1 << (self->bits - 1); + left = Px + diff; + left = (u16)(left % 65536); + if (self->linearize) + linear = self->linearize[left]; + else + linear = left; + thisrow[col++] = left; + out[c++] = linear; + if (self->ix >= self->datalen) { + TINY_DNG_DPRINTF("ix = %d, datalen = %d\n", self->ix, self->datalen); + return ret; + } + --write; + int rowcount = self->x - 1; + while (rowcount--) { + int _errcode = LJ92_ERROR_NONE; + diff = nextdiff(self, self->num_huff_idx - 1, 0, &_errcode); + if (_errcode != LJ92_ERROR_NONE) { + return _errcode; + } + Px = left; + left = Px + diff; + left = (u16)(left % 65536); + if (self->linearize) + linear = self->linearize[left]; + else + linear = left; + thisrow[col++] = left; + out[c++] = linear; + // TINY_DNG_DPRINTF("%d %d %d %d + // %x\n",col-1,diff,left,thisrow[col-1],&thisrow[col-1]); + if (self->ix >= self->datalen) { + TINY_DNG_DPRINTF("a: self->ix = %d, datalen = %d\n", self->ix, + self->datalen); + return ret; + } + if (--write == 0) { + out += self->skiplen; + write = self->writelen; + } + } + temprow = lastrow; + lastrow = thisrow; + thisrow = temprow; + row++; + // TINY_DNG_DPRINTF("%x %x\n",thisrow,lastrow); + while (c < pixels) { + col = 0; + int _errcode = LJ92_ERROR_NONE; + diff = nextdiff(self, self->num_huff_idx - 1, 0, &_errcode); + if (_errcode != LJ92_ERROR_NONE) { + return _errcode; + } + Px = lastrow[col]; // Use value above for first pixel in row + left = Px + diff; + left = (u16)(left % 65536); + if (self->linearize) { + if (left > self->linlen) return LJ92_ERROR_CORRUPT; + linear = self->linearize[left]; + } else + linear = left; + thisrow[col++] = left; + // TINY_DNG_DPRINTF("%d %d %d %d\n",col,diff,left,lastrow[col]); + out[c++] = linear; + if (self->ix >= self->datalen) break; + rowcount = self->x - 1; + if (--write == 0) { + out += self->skiplen; + write = self->writelen; + } + while (rowcount--) { + int errcode_d2 = LJ92_ERROR_NONE; + diff = nextdiff(self, self->num_huff_idx - 1, 0, &errcode_d2); + if (errcode_d2 != LJ92_ERROR_NONE) { + return errcode_d2; + } + + Px = lastrow[col] + ((left - lastrow[col - 1]) >> 1); + left = Px + diff; + left = (u16)(left % 65536); + // TINY_DNG_DPRINTF("%d %d %d %d %d + // %x\n",col,diff,left,lastrow[col],lastrow[col-1],&lastrow[col]); + if (self->linearize) { + if (left > self->linlen) return LJ92_ERROR_CORRUPT; + linear = self->linearize[left]; + } else + linear = left; + thisrow[col++] = left; + out[c++] = linear; + if (--write == 0) { + out += self->skiplen; + write = self->writelen; + } + } + temprow = lastrow; + lastrow = thisrow; + thisrow = temprow; + if (self->ix >= self->datalen) break; + } + if (c >= pixels) ret = LJ92_ERROR_NONE; + return ret; +} +#endif + +static int parseScan(ljp* self) { + int ret = LJ92_ERROR_CORRUPT; + memset(self->sssshist, 0, sizeof(self->sssshist)); + self->ix = self->scanstart; + int compcount = self->data[self->ix + 2]; + TINY_DNG_DPRINTF("comp count = %d\n", compcount); + int pred = self->data[self->ix + 3 + 2 * compcount]; + TINY_DNG_DPRINTF("predicator %d\n", pred); + + if (pred < 0 || pred > 7) return ret; + + // Disable until parsePred6() consideres self->components. + // if (pred == 6) return parsePred6(self); // Fast path + + // TINY_DNG_DPRINTF("pref = %d\n", pred); + self->ix += BEH(self->data[self->ix]); + self->cnt = 0; + self->b = 0; + // int write = self->writelen; + // Now need to decode huffman coded values + // int c = 0; + // int pixels = self->y * self->x * self->components; + u16* out = self->image; + u16* thisrow = self->outrow[0]; + u16* lastrow = self->outrow[1]; + + // First pixel predicted from base value + int diff; + int Px = 0; + // int col = 0; + // int row = 0; + int left = 0; + // TINY_DNG_DPRINTF("w = %d, h = %d, components = %d, skiplen = %d\n", + // self->x, + // self->y, + // self->components, self->skiplen); + for (int row = 0; row < self->y; row++) { + // TINY_DNG_DPRINTF("row = %d / %d\n", row, self->y); + // TINY_DNG_DPRINTF("thisrow %p, lastrow %p\n", thisrow, lastrow); + for (int col = 0; col < self->x; col++) { + int colx = col * self->components; + + // + // NOTE: pixel data is stored in interleaved manner(RGBRGBRGB...) + // + for (int c = 0; c < self->components; c++) { + // TINY_DNG_DPRINTF("c = %d, col = %d, row = %d\n", c, col, row); + if ((col == 0) && (row == 0)) { + Px = 1 << (self->bits - 1); + } else if (row == 0) { + // Px = left; + if (col > 0) { + // ok + } else { + //TINY_DNG_ASSERT(col > 0, "Unexpected col."); + return LJ92_ERROR_CORRUPT; + } + Px = thisrow[(col - 1) * self->components + c]; + } else if (col == 0) { + Px = lastrow[c]; // Use value above for first pixel in row + } else { + int prev_colx = (col - 1) * self->components; + + // previous pixel + left = thisrow[prev_colx + c]; + + // TINY_DNG_DPRINTF("pred = %d\n", pred); + switch (pred) { + case 0: + Px = 0; + break; // No prediction... should not be used + case 1: + Px = thisrow[prev_colx + c]; + break; + case 2: + Px = lastrow[colx + c]; + break; + case 3: + Px = lastrow[prev_colx + c]; + break; + case 4: + Px = left + lastrow[colx + c] - lastrow[prev_colx + c]; + break; + case 5: + Px = left + ((lastrow[colx + c] - lastrow[prev_colx + c]) >> 1); + break; + case 6: + Px = lastrow[colx + c] + ((left - lastrow[prev_colx + c]) >> 1); + break; + case 7: + Px = (left + lastrow[colx + c]) >> 1; + // printf("Px = %d, left = %d, lastrow[colx + c] = %d\n", Px, + // left, lastrow[colx + c]); + break; + } + } + + int huff_idx = c; + if (c >= self->num_huff_idx) { + // Invalid huffman table index. + // Currently we assume # of huffman tables is 1. + TINY_DNG_CHECK_AND_RETURN_C(self->num_huff_idx == 1, LJ92_ERROR_CORRUPT); + huff_idx = 0; // Look up the first huffman table. + } + + int errcode = LJ92_ERROR_NONE; + diff = nextdiff(self, huff_idx, Px, &errcode); + if (errcode != LJ92_ERROR_NONE) { + return errcode; + } + + left = Px + diff; + + if (left >= 0) { + // ok + } else { + //TINY_DNG_ASSERT(left >= 0, "left value must be positive."); + return LJ92_ERROR_CORRUPT; + } + + if (left < 65536) { + // ok + } else { + //TINY_DNG_ASSERT(left < 65536, + // "left value must be less than u16 max(65536)."); + return LJ92_ERROR_CORRUPT; + } + + left = (u16)(left % 65536); + // TINY_DNG_DPRINTF("row[%d] col[%d] c[%d] Px = %d, diff = %d, left = + // %d\n", row, col, c, Px, diff, left); + // Apple ProRAW gives -1 for `left`(=65535?), so uncommented negative + // left value check. + // TINY_DNG_ASSERT(left >= 0 && left < (1 << self->bits), + // "Error huffman decoding."); + // TINY_DNG_DPRINTF("pix = %d\n", left); + // TINY_DNG_DPRINTF("%d %d %d\n",c,diff,left); + int linear; // TODO: use u16? + if (self->linearize) { + if (left > self->linlen) return LJ92_ERROR_CORRUPT; + linear = self->linearize[u16(left)]; + } else { + linear = left; + } + + // TINY_DNG_DPRINTF("linear = %d\n", linear); + thisrow[colx + c] = left; + out[colx + c] = linear; + } // c + } // col + + // Swap pointers for input and working row buffer + u16* temprow = lastrow; + lastrow = thisrow; + thisrow = temprow; + + // Advance row of output buffer. + // NOTE: multiply + out += self->x * self->components + self->skiplen; + // TINY_DNG_DPRINTF("out = %p, %p, diff = %lld\n", out, self->image, out - + // self->image); + + } // row + + ret = LJ92_ERROR_NONE; + + // TINY_DNG_DPRINTF("out written = %d\n", int(out - self->image)); + + // if (++col == self->x) { + // col = 0; + // row++; + //} + // if (--write == 0) { + // out += self->skiplen; + // write = self->writelen; + //} + // if (self->ix >= self->datalen + 2) break; + + // if (c >= pixels) ret = LJ92_ERROR_NONE; + /*for (int h=0;h<17;h++) { + TINY_DNG_DPRINTF("ssss:%d=%d + (%f)\n",h,self->sssshist[h],(float)self->sssshist[h]/(float)(pixels)); + }*/ + return ret; +} + +static int parseImage(ljp* self) { + // TINY_DNG_DPRINTF("parseImage\n"); + int ret = LJ92_ERROR_NONE; + while (1) { + int nextMarker = find(self); + TINY_DNG_DPRINTF("marker = 0x%08x\n", nextMarker); + if (nextMarker == 0xc4) { + TINY_DNG_DPRINTF("Parse huffman table.\n"); + ret = parseHuff(self); + } else if (nextMarker == 0xc3) { + ret = parseSof3(self); + } else if (nextMarker == 0xfe) { // Comment + ret = parseBlock(self, nextMarker); + } else if (nextMarker == 0xd9) { // End of image + break; + } else if (nextMarker == 0xda) { + self->scanstart = self->ix; + ret = LJ92_ERROR_NONE; + break; + } else if (nextMarker == -1) { + ret = LJ92_ERROR_CORRUPT; + break; + } else + ret = parseBlock(self, nextMarker); + if (ret != LJ92_ERROR_NONE) break; + } + return ret; +} + +static int findSoI(ljp* self) { + int ret = LJ92_ERROR_CORRUPT; + if (find(self) == 0xd8) { + ret = parseImage(self); + } else { + TINY_DNG_DPRINTF("findSoI: corrupt\n"); + } + return ret; +} + +static void free_memory(ljp* self) { +#ifdef SLOW_HUFF + free(self->maxcode); + self->maxcode = NULL; + free(self->mincode); + self->mincode = NULL; + free(self->valptr); + self->valptr = NULL; + free(self->huffval); + self->huffval = NULL; + free(self->huffsize); + self->huffsize = NULL; + free(self->huffcode); + self->huffcode = NULL; +#else + for (int i = 0; i < self->num_huff_idx; i++) { + free(self->hufflut[i]); + self->hufflut[i] = NULL; + } +#endif + free(self->rowcache); + self->rowcache = NULL; +} + +int lj92_open(lj92* lj, const uint8_t* data, int datalen, int* width, + int* height, int* bitdepth) { + ljp* self = (ljp*)calloc(sizeof(ljp), 1); + if (self == NULL) return LJ92_ERROR_NO_MEMORY; + + self->data = (u8*)data; + self->dataend = self->data + datalen; + self->datalen = datalen; + self->num_huff_idx = 0; + + int ret = findSoI(self); + + if (ret == LJ92_ERROR_NONE) { + u16* rowcache = (u16*)calloc(self->x * self->components * 2, sizeof(u16)); + if (rowcache == NULL) + ret = LJ92_ERROR_NO_MEMORY; + else { + self->rowcache = rowcache; + self->outrow[0] = rowcache; + self->outrow[1] = &rowcache[self->x * self->components]; + } + } + + if (ret != LJ92_ERROR_NONE) { // Failed, clean up + *lj = NULL; + free_memory(self); + free(self); + } else { + *width = self->x; + *height = self->y; + *bitdepth = self->bits; + *lj = self; + } + return ret; +} + +int lj92_decode(lj92 lj, uint16_t* target, int writeLength, int skipLength, + uint16_t* linearize, int linearizeLength) { + int ret = LJ92_ERROR_NONE; + ljp* self = lj; + if (self == NULL) return LJ92_ERROR_BAD_HANDLE; + self->image = target; + self->writelen = writeLength; + self->skiplen = skipLength; + self->linearize = linearize; + self->linlen = linearizeLength; + ret = parseScan(self); + return ret; +} + +void lj92_close(lj92 lj) { + ljp* self = lj; + if (self != NULL) free_memory(self); + free(self); +} + +#if 0 // not used in tinydngloader at the moment. +// Fix of https://github.com/ilia3101/MLV-App/pull/151/files is not reflected here fully. +/* Encoder implementation */ + +// Very simple count leading zero implementation. +static int clz32(unsigned int x) { + int n; + if (x == 0) return 32; + for (n = 0; ((x & 0x80000000) == 0); n++, x <<= 1) + ; + return n; +} + +typedef struct _lje { + uint16_t* image; + int width; + int height; + int bitdepth; + int components; + int readLength; + int skipLength; + uint16_t* delinearize; + int delinearizeLength; + uint8_t* encoded; + int encodedWritten; + int encodedLength; + int hist[18]; // SSSS frequency histogram + int bits[18]; + int huffval[18]; + u16 huffenc[18]; + u16 huffbits[18]; + int huffsym[18]; +} lje; + +int frequencyScan(lje* self) { + // Scan through the tile using the standard type 6 prediction + // Need to cache the previous 2 row in target coordinates because of tiling + uint16_t* pixel = self->image; + int pixcount = self->width * self->height; + int scan = self->readLength; + uint16_t* rowcache = (uint16_t*)calloc(1, self->width * self->components * 4); + uint16_t* rows[2]; + rows[0] = rowcache; + rows[1] = &rowcache[self->width * self->components]; + + int col = 0; + int row = 0; + int Px = 0; + int32_t diff = 0; + int maxval = (1 << self->bitdepth); + + // TODO: consider self->components + while (pixcount--) { + uint16_t p = *pixel; + if (self->delinearize) { + if (p >= self->delinearizeLength) { + free(rowcache); + return LJ92_ERROR_TOO_WIDE; + } + p = self->delinearize[p]; + } + if (p >= maxval) { + free(rowcache); + return LJ92_ERROR_TOO_WIDE; + } + rows[1][col] = p; + + if ((row == 0) && (col == 0)) + Px = 1 << (self->bitdepth - 1); + else if (row == 0) + Px = rows[1][col - 1]; + else if (col == 0) + Px = rows[0][col]; + else + Px = rows[0][col] + ((rows[1][col - 1] - rows[0][col - 1]) >> 1); + diff = rows[1][col] - Px; + diff = diff%65536; + // int ssss = 32 - __builtin_clz(abs(diff)); + int ssss = 32 - clz32(abs(diff)); + if (diff == 0) ssss = 0; + self->hist[ssss]++; + // TINY_DNG_DPRINTF("%d %d %d %d %d %d\n",col,row,p,Px,diff,ssss); + pixel++; + scan--; + col++; + if (scan == 0) { + pixel += self->skipLength; + scan = self->readLength; + } + if (col == self->width) { + uint16_t* tmprow = rows[1]; + rows[1] = rows[0]; + rows[0] = tmprow; + col = 0; + row++; + } + } +#ifdef LJ92_DEBUG + int sort[17]; + for (int h = 0; h < 17; h++) { + sort[h] = h; + TINY_DNG_DPRINTF("%d:%d\n", h, self->hist[h]); + } +#endif + free(rowcache); + return LJ92_ERROR_NONE; +} + +void createEncodeTable(lje* self) { + float freq[18]; + int codesize[18]; + int others[18]; + + // Calculate frequencies + float totalpixels = self->width * self->height; + for (int i = 0; i < 17; i++) { + freq[i] = (float)(self->hist[i]) / totalpixels; +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("%d:%f\n", i, freq[i]); +#endif + codesize[i] = 0; + others[i] = -1; + } + codesize[17] = 0; + others[17] = -1; + freq[17] = 1.0f; + + float v1f, v2f; + int v1, v2; + + while (1) { + v1f = 3.0f; + v1 = -1; + for (int i = 0; i < 18; i++) { + if ((freq[i] <= v1f) && (freq[i] > 0.0f)) { + v1f = freq[i]; + v1 = i; + } + } +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("v1:%d,%f\n", v1, v1f); +#endif + v2f = 3.0f; + v2 = -1; + for (int i = 0; i < 18; i++) { + if (i == v1) continue; + if ((freq[i] < v2f) && (freq[i] > 0.0f)) { + v2f = freq[i]; + v2 = i; + } + } + if (v2 == -1) break; // Done + + freq[v1] += freq[v2]; + freq[v2] = 0.0f; + + while (1) { + codesize[v1]++; + if (others[v1] == -1) break; + v1 = others[v1]; + } + others[v1] = v2; + while (1) { + codesize[v2]++; + if (others[v2] == -1) break; + v2 = others[v2]; + } + } + int* bits = self->bits; + memset(bits, 0, sizeof(self->bits)); + for (int i = 0; i < 18; i++) { + if (codesize[i] != 0) { + bits[codesize[i]]++; + } + } +#ifdef LJ92_DEBUG + for (int i = 0; i < 17; i++) { + TINY_DNG_DPRINTF("bits:%d,%d,%d\n", i, bits[i], codesize[i]); + } +#endif + int* huffval = self->huffval; + int i = 1; + int k = 0; + int j; + memset(huffval, 0, sizeof(self->huffval)); + while (i <= 32) { + j = 0; + while (j < 17) { + if (codesize[j] == i) { + huffval[k++] = j; + } + j++; + } + i++; + } +#ifdef LJ92_DEBUG + for (i = 0; i < 17; i++) { + TINY_DNG_DPRINTF("i=%d,huffval[i]=%x\n", i, huffval[i]); + } +#endif + int maxbits = 16; + while (maxbits > 0) { + if (bits[maxbits]) break; + maxbits--; + } + u16* huffenc = self->huffenc; + u16* huffbits = self->huffbits; + int* huffsym = self->huffsym; + memset(huffenc, 0, sizeof(self->huffenc)); + memset(huffbits, 0, sizeof(self->huffbits)); + memset(self->huffsym, 0, sizeof(self->huffsym)); + i = 0; + int hv = 0; + int rv = 0; + int vl = 0; // i + // int hcode; + int bitsused = 1; + int sym = 0; + // TINY_DNG_DPRINTF("%04x:%x:%d:%x\n",i,huffvals[hv],bitsused,1<<(maxbits-bitsused)); + while (i < 1 << maxbits) { + if (bitsused > maxbits) { + break; // Done. Should never get here! + } + if (vl >= bits[bitsused]) { + bitsused++; + vl = 0; + continue; + } + if (rv == 1 << (maxbits - bitsused)) { + rv = 0; + vl++; + hv++; + // TINY_DNG_DPRINTF("%04x:%x:%d:%x\n",i,huffvals[hv],bitsused,1<<(maxbits-bitsused)); + continue; + } + huffbits[sym] = bitsused; + huffenc[sym++] = i >> (maxbits - bitsused); + // TINY_DNG_DPRINTF("%d %d %d\n",i,bitsused,hcode); + i += (1 << (maxbits - bitsused)); + rv = 1 << (maxbits - bitsused); + } + for (i = 0; i < 17; i++) { + if (huffbits[i] > 0) { + huffsym[huffval[i]] = i; + } +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("huffval[%d]=%d,huffenc[%d]=%x,bits=%d\n", i, huffval[i], + i, huffenc[i], huffbits[i]); +#endif + if (huffbits[i] > 0) { + huffsym[huffval[i]] = i; + } + } +#ifdef LJ92_DEBUG + for (i = 0; i < 17; i++) { + TINY_DNG_DPRINTF("huffsym[%d]=%d\n", i, huffsym[i]); + } +#endif +} + +// TODO: Support components of 2> +void writeHeader(lje* self) { + int w = self->encodedWritten; + uint8_t* e = self->encoded; + e[w++] = 0xff; + e[w++] = 0xd8; // SOI + e[w++] = 0xff; + e[w++] = 0xc3; // SOF3 + // Write SOF + e[w++] = 0x0; + e[w++] = 11; // Lf, frame header length + e[w++] = self->bitdepth; + e[w++] = self->height >> 8; + e[w++] = self->height & 0xFF; + e[w++] = self->width >> 8; + e[w++] = self->width & 0xFF; + e[w++] = 1; // Components + e[w++] = 0; // Component ID + e[w++] = 0x11; // Component X/Y + e[w++] = 0; // Unused (Quantisation) + e[w++] = 0xff; + e[w++] = 0xc4; // HUFF + // Write HUFF + int count = 0; + for (int i = 0; i < 17; i++) { + count += self->bits[i]; + } + e[w++] = 0x0; + e[w++] = 17 + 2 + count; // Lf, frame header length + e[w++] = 0; // Table ID + for (int i = 1; i < 17; i++) { + e[w++] = self->bits[i]; + } + for (int i = 0; i < count; i++) { + e[w++] = self->huffval[i]; + } + e[w++] = 0xff; + e[w++] = 0xda; // SCAN + // Write SCAN + e[w++] = 0x0; + e[w++] = 8; // Ls, scan header length + e[w++] = 1; // Components + e[w++] = 0; // + e[w++] = 0; // + e[w++] = 6; // Predictor + e[w++] = 0; // + e[w++] = 0; // + self->encodedWritten = w; +} + +void writePost(lje* self) { + int w = self->encodedWritten; + uint8_t* e = self->encoded; + e[w++] = 0xff; + e[w++] = 0xd9; // EOI + self->encodedWritten = w; +} + +void writeBody(lje* self) { + // Scan through the tile using the standard type 6 prediction + // Need to cache the previous 2 row in target coordinates because of tiling + uint16_t* pixel = self->image; + int pixcount = self->width * self->height; + int scan = self->readLength; + uint16_t* rowcache = (uint16_t*)calloc(1, self->width * self->components * 4); + uint16_t* rows[2]; + rows[0] = rowcache; + rows[1] = &rowcache[self->width]; + + int col = 0; + int row = 0; + int Px = 0; + int32_t diff = 0; + int bitcount = 0; + uint8_t* out = self->encoded; + int w = self->encodedWritten; + uint8_t next = 0; + uint8_t nextbits = 8; + while (pixcount--) { + uint16_t p = *pixel; + if (self->delinearize) p = self->delinearize[p]; + rows[1][col] = p; + + if ((row == 0) && (col == 0)) + Px = 1 << (self->bitdepth - 1); + else if (row == 0) + Px = rows[1][col - 1]; + else if (col == 0) + Px = rows[0][col]; + else + Px = rows[0][col] + ((rows[1][col - 1] - rows[0][col - 1]) >> 1); + diff = rows[1][col] - Px; + // int ssss = 32 - __builtin_clz(abs(diff)); + int ssss = 32 - clz32(abs(diff)); + if (diff == 0) ssss = 0; + // TINY_DNG_DPRINTF("%d %d %d %d %d\n",col,row,Px,diff,ssss); + + // Write the huffman code for the ssss value + int huffcode = self->huffsym[ssss]; + int huffenc = self->huffenc[huffcode]; + int huffbits = self->huffbits[huffcode]; + bitcount += huffbits + ssss; + + int vt = ssss > 0 ? (1 << (ssss - 1)) : 0; +// TINY_DNG_DPRINTF("%d %d %d %d\n",rows[1][col],Px,diff,Px+diff); +#ifdef LJ92_DEBUG +#endif + if (diff < vt) diff += (1 << (ssss)) - 1; + + // Write the ssss + while (huffbits > 0) { + int usebits = huffbits > nextbits ? nextbits : huffbits; + // Add top usebits from huffval to next usebits of nextbits + int tophuff = huffenc >> (huffbits - usebits); + next |= (tophuff << (nextbits - usebits)); + nextbits -= usebits; + huffbits -= usebits; + huffenc &= (1 << huffbits) - 1; + if (nextbits == 0) { + out[w++] = next; + if (next == 0xff) out[w++] = 0x0; + next = 0; + nextbits = 8; + } + } + // Write the rest of the bits for the value + + while (ssss > 0) { + int usebits = ssss > nextbits ? nextbits : ssss; + // Add top usebits from huffval to next usebits of nextbits + int tophuff = diff >> (ssss - usebits); + next |= (tophuff << (nextbits - usebits)); + nextbits -= usebits; + ssss -= usebits; + diff &= (1 << ssss) - 1; + if (nextbits == 0) { + out[w++] = next; + if (next == 0xff) out[w++] = 0x0; + next = 0; + nextbits = 8; + } + } + + // TINY_DNG_DPRINTF("%d %d\n",diff,ssss); + pixel++; + scan--; + col++; + if (scan == 0) { + pixel += self->skipLength; + scan = self->readLength; + } + if (col == self->width) { + uint16_t* tmprow = rows[1]; + rows[1] = rows[0]; + rows[0] = tmprow; + col = 0; + row++; + } + } + // Flush the final bits + if (nextbits < 8) { + out[w++] = next; + if (next == 0xff) out[w++] = 0x0; + } +#ifdef LJ92_DEBUG + int sort[17]; + for (int h = 0; h < 17; h++) { + sort[h] = h; + TINY_DNG_DPRINTF("%d:%d\n", h, self->hist[h]); + } + TINY_DNG_DPRINTF("Total bytes: %d\n", bitcount >> 3); +#endif + free(rowcache); + self->encodedWritten = w; +} + +/* Encoder + * Read tile from an image and encode in one shot + * Return the encoded data + */ +int lj92_encode(uint16_t* image, int width, int height, int bitdepth, + int readLength, int skipLength, uint16_t* delinearize, + int delinearizeLength, uint8_t** encoded, int* encodedLength) { + int ret = LJ92_ERROR_NONE; + + lje* self = (lje*)calloc(sizeof(lje), 1); + if (self == NULL) return LJ92_ERROR_NO_MEMORY; + self->image = image; + self->width = width; + self->height = height; + self->bitdepth = bitdepth; + self->readLength = readLength; + self->skipLength = skipLength; + self->delinearize = delinearize; + self->delinearizeLength = delinearizeLength; + self->encodedLength = width * height * 3 + 200; + self->encoded = (uint8_t*)malloc(self->encodedLength); + if (self->encoded == NULL) { + free(self); + return LJ92_ERROR_NO_MEMORY; + } + // Scan through data to gather frequencies of ssss prefixes + ret = frequencyScan(self); + if (ret != LJ92_ERROR_NONE) { + free(self->encoded); + free(self); + return ret; + } + // Create encoded table based on frequencies + createEncodeTable(self); + // Write JPEG head and scan header + writeHeader(self); + // Scan through and do the compression + writeBody(self); + // Finish + writePost(self); +#ifdef LJ92_DEBUG + TINY_DNG_DPRINTF("written:%d\n", self->encodedWritten); +#endif + self->encoded = (uint8_t*)realloc(self->encoded, self->encodedWritten); + self->encodedLength = self->encodedWritten; + *encoded = self->encoded; + *encodedLength = self->encodedLength; + + free(self); + + return ret; +} +#endif + +// End liblj92 --------------------------------------------------------- +} // namespace + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif +#endif + +typedef enum { + TAG_NEW_SUBFILE_TYPE = 254, + TAG_SUBFILE_TYPE = 255, + TAG_IMAGE_WIDTH = 256, + TAG_IMAGE_HEIGHT = 257, + TAG_BITS_PER_SAMPLE = 258, + TAG_COMPRESSION = 259, + TAG_STRIP_OFFSET = 273, + TAG_ORIENTATION = 274, + TAG_SAMPLES_PER_PIXEL = 277, + TAG_ROWS_PER_STRIP = 278, + TAG_STRIP_BYTE_COUNTS = 279, + TAG_PLANAR_CONFIGURATION = 284, + TAG_PREDICTOR = 317, + TAG_SUB_IFDS = 330, + TAG_TILE_WIDTH = 322, + TAG_TILE_LENGTH = 323, + TAG_TILE_OFFSETS = 324, + TAG_TILE_BYTE_COUNTS = 325, + TAG_SAMPLE_FORMAT = 339, + TAG_JPEG_IF_OFFSET = 513, + TAG_JPEG_IF_BYTE_COUNT = 514, + TAG_CFA_PATTERN_DIM = 33421, + TAG_CFA_PATTERN = 33422, + TAG_CFA_PLANE_COLOR = 50710, + TAG_CFA_LAYOUT = 50711, + TAG_BLACK_LEVEL = 50714, + TAG_WHITE_LEVEL = 50717, + TAG_COLOR_MATRIX1 = 50721, + TAG_COLOR_MATRIX2 = 50722, + TAG_CAMERA_CALIBRATION1 = 50723, + TAG_CAMERA_CALIBRATION2 = 50724, + TAG_DNG_VERSION = 50706, + TAG_ANALOG_BALANCE = 50727, + TAG_AS_SHOT_NEUTRAL = 50728, + TAG_CALIBRATION_ILLUMINANT1 = 50778, + TAG_CALIBRATION_ILLUMINANT2 = 50779, + TAG_ACTIVE_AREA = 50829, + TAG_FORWARD_MATRIX1 = 50964, + TAG_FORWARD_MATRIX2 = 50965, + + // CR2 extension + // http://lclevy.free.fr/cr2/ + TAG_CR2_META0 = 50648, + TAG_CR2_META1 = 50656, + TAG_CR2_SLICES = 50752, + TAG_CR2_META2 = 50885, + + // + // OpCodeList + // + TAG_OPCODE_LIST1 = 0xc740, + TAG_OPCODE_LIST2 = 0xc741, + TAG_OPCODE_LIST3 = 0xc742, + + // TODO: + // TAG_NOISE_PROFILE = 0xc761 + + // DNG 1.6(Apple ProRAW) + // ahttps://helpx.adobe.com/photoshop/kb/dng-specification-tags.html + TAG_SEMANTIC_NAME = 52526, // Type: ASCII, Count: String length including + // null, Value: null-terminated string + + TAG_INVALID = 65535 +} TiffTag; + +typedef enum { + OPCODE_LIST_WARP_RECTILINEAR = 1, + OPCODE_LIST_WARP_FISHEYE = 2, + OPCODE_LIST_FIX_VIGNETTE_RADIAL = 3, + OPCODE_LIST_FIX_BAD_PIXELS_CONSTANT = 4, + OPCODE_LIST_FIX_BAD_PIXELS_LIST = 5, + OPCODE_LIST_TRIM_BOUNDS = 6, + OPCODE_LIST_MAP_TABLE = 7, + OPCODE_LIST_MAP_POLYNOMIAL = 8, + OPCODE_LIST_GAIN_MAP = 9, + OPCODE_LIST_DELTA_PER_ROW = 10, + OPCODE_LIST_DELTA_PER_COLUMN = 11, + OPCODE_LIST_SCALE_PER_ROW = 12, + OPCODE_LIST_SCALE_PER_COLUMN = 13 +} OpCodeListValue; + +static bool IsBigEndian(); + +static void swap2(unsigned short* val) { + unsigned short tmp = *val; + unsigned char* dst = reinterpret_cast<unsigned char*>(val); + unsigned char* src = reinterpret_cast<unsigned char*>(&tmp); + + dst[0] = src[1]; + dst[1] = src[0]; +} + +static void swap4(unsigned int* val) { + unsigned int tmp = *val; + unsigned char* dst = reinterpret_cast<unsigned char*>(val); + unsigned char* src = reinterpret_cast<unsigned char*>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +} + +static inline void swap4(int* val) { + int tmp = *val; + unsigned char* dst = reinterpret_cast<unsigned char*>(val); + unsigned char* src = reinterpret_cast<unsigned char*>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +} + +static inline void swap8(uint64_t* val) { + uint64_t tmp = (*val); + unsigned char* dst = reinterpret_cast<unsigned char*>(val); + unsigned char* src = reinterpret_cast<unsigned char*>(&tmp); + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +} + +static inline void swap8(int64_t* val) { + int64_t tmp = (*val); + unsigned char* dst = reinterpret_cast<unsigned char*>(val); + unsigned char* src = reinterpret_cast<unsigned char*>(&tmp); + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +} + +// For unaligned read + +static void cpy2(unsigned short* dst_val, const unsigned short* src_val) { + unsigned char* dst = reinterpret_cast<unsigned char*>(dst_val); + const unsigned char* src = reinterpret_cast<const unsigned char*>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; +} + +static void cpy2(short* dst_val, const short* src_val) { + unsigned char* dst = reinterpret_cast<unsigned char*>(dst_val); + const unsigned char* src = reinterpret_cast<const unsigned char*>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; +} + +static void cpy4(unsigned int* dst_val, const unsigned int* src_val) { + unsigned char* dst = reinterpret_cast<unsigned char*>(dst_val); + const unsigned char* src = reinterpret_cast<const unsigned char*>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +static void cpy4(int* dst_val, const int* src_val) { + unsigned char* dst = reinterpret_cast<unsigned char*>(dst_val); + const unsigned char* src = reinterpret_cast<const unsigned char*>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +static void cpy8(uint64_t* dst_val, const uint64_t* src_val) { + unsigned char* dst = reinterpret_cast<unsigned char*>(dst_val); + const unsigned char* src = reinterpret_cast<const unsigned char*>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; +} + +static void cpy8(int64_t* dst_val, const int64_t* src_val) { + unsigned char* dst = reinterpret_cast<unsigned char*>(dst_val); + const unsigned char* src = reinterpret_cast<const unsigned char*>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; +} + + +/// +/// Simple stream reader +/// +class StreamReader { + public: + explicit StreamReader(const uint8_t* binary, const size_t length, + const bool swap_endian) + : binary_(binary), length_(length), swap_endian_(swap_endian), idx_(0) { + (void)pad_; + } + + bool seek_set(const uint64_t offset) const { + if (offset > length_) { + return false; + } + + idx_ = offset; + return true; + } + + bool seek_from_currect(const int64_t offset) const { + if ((int64_t(idx_) + offset) < 0) { + return false; + } + + if (size_t((int64_t(idx_) + offset)) > length_) { + return false; + } + + idx_ = size_t(int64_t(idx_) + offset); + return true; + } + + size_t read(const size_t n, const uint64_t dst_len, + unsigned char* dst) const { + size_t len = n; + if ((idx_ + len) > length_) { + len = length_ - idx_; + } + + if (len > 0) { + if (dst_len < len) { + // dst does not have enough space. return 0 for a while. + return 0; + } + + memcpy(dst, &binary_[idx_], len); + idx_ += len; + return len; + + } else { + return 0; + } + } + + bool read1(unsigned char* ret) const { + if ((idx_ + 1) > length_) { + return false; + } + + const unsigned char val = binary_[idx_]; + + (*ret) = val; + idx_ += 1; + + return true; + } + + bool read_bool(bool* ret) const { + if ((idx_ + 1) > length_) { + return false; + } + + const char val = static_cast<const char>(binary_[idx_]); + + (*ret) = bool(val); + idx_ += 1; + + return true; + } + + bool read1(char* ret) const { + if ((idx_ + 1) > length_) { + return false; + } + + const char val = static_cast<const char>(binary_[idx_]); + + (*ret) = val; + idx_ += 1; + + return true; + } + + bool read2(unsigned short* ret) const { + if ((idx_ + 2) > length_) { + return false; + } + + unsigned short val = 0; + cpy2(&val, reinterpret_cast<const unsigned short*>(&binary_[idx_])); + + if (swap_endian_) { + swap2(&val); + } + + (*ret) = val; + idx_ += 2; + + return true; + } + + bool read2(short* ret) const { + if ((idx_ + 2) > length_) { + return false; + } + + short val = 0; + cpy2(&val, reinterpret_cast<const short*>(&binary_[idx_])); + + if (swap_endian_) { + swap2(reinterpret_cast<unsigned short*>(&val)); + } + + (*ret) = val; + idx_ += 2; + + return true; + } + + bool read4(unsigned int* ret) const { + if ((idx_ + 4) > length_) { + return false; + } + + unsigned int val = 0; + cpy4(&val, reinterpret_cast<const unsigned int*>(&binary_[idx_])); + + if (swap_endian_) { + swap4(&val); + } + + (*ret) = val; + idx_ += 4; + + return true; + } + + bool read4(int* ret) const { + if ((idx_ + 4) > length_) { + return false; + } + + int val = 0; + cpy4(&val, reinterpret_cast<const int*>(&binary_[idx_])); + + if (swap_endian_) { + swap4(&val); + } + + (*ret) = val; + idx_ += 4; + + return true; + } + + bool read8(uint64_t* ret) const { + if ((idx_ + 8) > length_) { + return false; + } + + uint64_t val = 0; + cpy8(&val, reinterpret_cast<const uint64_t*>(&binary_[idx_])); + + if (swap_endian_) { + swap8(&val); + } + + (*ret) = val; + idx_ += 8; + + return true; + } + + bool read8(int64_t* ret) const { + if ((idx_ + 8) > length_) { + return false; + } + + int64_t val = 0; + cpy8(&val, reinterpret_cast<const int64_t*>(&binary_[idx_])); + + if (swap_endian_) { + swap8(&val); + } + + (*ret) = val; + idx_ += 8; + + return true; + } + + bool read_float(float* ret) const { + if (!ret) { + return false; + } + + float value = 0.0f; + if (!read4(reinterpret_cast<int*>(&value))) { + return false; + } + + (*ret) = value; + + return true; + } + + bool read_double(double* ret) const { + if (!ret) { + return false; + } + + double value = 0.0; + if (!read8(reinterpret_cast<uint64_t*>(&value))) { + return false; + } + + (*ret) = value; + + return true; + } + + bool read_uint(int type, unsigned int* ret) const { + // @todo {8, 9, 10, 11, 12} + if (type == 3) { + unsigned short val; + if (!read2(&val)) { + return false; + } + (*ret) = static_cast<unsigned int>(val); + return true; + } else if (type == 5) { + unsigned int val0; + if (!read4(&val0)) { + return false; + } + + unsigned int val1; + if (!read4(&val1)) { + return false; + } + + if (val1 == 0) { + // Seems invalid + return false; + } + + (*ret) = static_cast<unsigned int>(val0 / val1); + return true; + + } else if (type == 4) { + unsigned int val; + if (!read4(&val)) { + return false; + } + (*ret) = val; + return true; + } else { + return false; + } + } + + bool read_real(int type, double* ret) const { + // @todo { Support more types. } + + if (type == TYPE_RATIONAL) { + unsigned int num; + if (!read4(&num)) { + return false; + } + unsigned int denom; + if (!read4(&denom)) { + return false; + } + + (*ret) = static_cast<double>(num) / static_cast<double>(denom); + return true; + } else if (type == TYPE_SRATIONAL) { + int num; + if (!read4(&num)) { + return false; + } + int denom; + if (!read4(&denom)) { + return false; + } + + (*ret) = static_cast<double>(num) / static_cast<double>(denom); + return true; + } else { + return false; + } + // never come here. + } + + // + // Returns a memory address. The begining of address is computed in + // relative(based on current seek pos). This function is useful when you just + // want to access the content in read-only mode. + // + // Note that the function does not change seek position after the call. + // This function does the bound check. + // + // @param[in] offset Extra byte offset. 0 = use current seek position. + // @param[in] length Byte length to map. + // + // @return nullptr when failed to map address. + // + const uint8_t* map_addr(size_t offset, const size_t length) { + if (length == 0) { + return NULL; + } + + if ((idx_ + offset) > length_) { + return NULL; + } + + if ((idx_ + offset + length) > length_) { + return NULL; + } + + return &binary_[idx_ + offset]; + } + + // + // Returns a memory address. The begining of address is specified by + // absolute(ignores current seek pos). This function is useful when you just + // want to access the content in read-only mode. + // + // Note that the function does not change seek position after the call. + // This function does the bound check. + // + // @param[in] pos Absolute position in bytes. + // @param[in] length Byte length to map. + // + // @return nullptr when failed to map address. + // + const uint8_t* map_abs_addr(size_t pos, const size_t length) { + if (length == 0) { + return NULL; + } + + if (pos > length_) { + return NULL; + } + + if ((pos + length) > length_) { + return NULL; + } + + return &binary_[pos]; + } + + size_t tell() const { return idx_; } + + const uint8_t* data() const { return binary_; } + + bool swap_endian() const { return swap_endian_; } + + size_t size() const { return length_; } + + private: + const uint8_t* binary_; + const size_t length_; + bool swap_endian_; + char pad_[7]; + mutable uint64_t idx_; +}; + +static bool GetTIFFTag(const StreamReader& sr, unsigned short* tag, + unsigned short* type, unsigned int* len, + unsigned int* saved_offt) { + if (!sr.read2(tag)) { + return false; + } + + if (!sr.read2(type)) { + return false; + } + + if (!sr.read4(len)) { + return false; + } + + (*saved_offt) = static_cast<unsigned int>(sr.tell()) + 4; + + size_t typesize_table[] = {1, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4}; + + if ((*len) * (typesize_table[(*type) < 14 ? (*type) : 0]) > 4) { + unsigned int base = 0; // fixme + unsigned int offt = 0; + if (!sr.read4(&offt)) { + return false; + } + if (!sr.seek_set(offt + base)) { + return false; + } + } + + return true; +} + +static void InitializeDNGImage(tinydng::DNGImage* image) { + image->version = 0; + + image->color_matrix1[0][0] = 1.0; + image->color_matrix1[0][1] = 0.0; + image->color_matrix1[0][2] = 0.0; + image->color_matrix1[1][0] = 0.0; + image->color_matrix1[1][1] = 1.0; + image->color_matrix1[1][2] = 0.0; + image->color_matrix1[2][0] = 0.0; + image->color_matrix1[2][1] = 0.0; + image->color_matrix1[2][2] = 1.0; + + image->color_matrix2[0][0] = 1.0; + image->color_matrix2[0][1] = 0.0; + image->color_matrix2[0][2] = 0.0; + image->color_matrix2[1][0] = 0.0; + image->color_matrix2[1][1] = 1.0; + image->color_matrix2[1][2] = 0.0; + image->color_matrix2[2][0] = 0.0; + image->color_matrix2[2][1] = 0.0; + image->color_matrix2[2][2] = 1.0; + + image->forward_matrix1[0][0] = 1.0; + image->forward_matrix1[0][1] = 0.0; + image->forward_matrix1[0][2] = 0.0; + image->forward_matrix1[1][0] = 0.0; + image->forward_matrix1[1][1] = 1.0; + image->forward_matrix1[1][2] = 0.0; + image->forward_matrix1[2][0] = 0.0; + image->forward_matrix1[2][1] = 0.0; + image->forward_matrix1[2][2] = 1.0; + + image->forward_matrix2[0][0] = 1.0; + image->forward_matrix2[0][1] = 0.0; + image->forward_matrix2[0][2] = 0.0; + image->forward_matrix2[1][0] = 0.0; + image->forward_matrix2[1][1] = 1.0; + image->forward_matrix2[1][2] = 0.0; + image->forward_matrix2[2][0] = 0.0; + image->forward_matrix2[2][1] = 0.0; + image->forward_matrix2[2][2] = 1.0; + + image->camera_calibration1[0][0] = 1.0; + image->camera_calibration1[0][1] = 0.0; + image->camera_calibration1[0][2] = 0.0; + image->camera_calibration1[1][0] = 0.0; + image->camera_calibration1[1][1] = 1.0; + image->camera_calibration1[1][2] = 0.0; + image->camera_calibration1[2][0] = 0.0; + image->camera_calibration1[2][1] = 0.0; + image->camera_calibration1[2][2] = 1.0; + + image->camera_calibration2[0][0] = 1.0; + image->camera_calibration2[0][1] = 0.0; + image->camera_calibration2[0][2] = 0.0; + image->camera_calibration2[1][0] = 0.0; + image->camera_calibration2[1][1] = 1.0; + image->camera_calibration2[1][2] = 0.0; + image->camera_calibration2[2][0] = 0.0; + image->camera_calibration2[2][1] = 0.0; + image->camera_calibration2[2][2] = 1.0; + + image->calibration_illuminant1 = LIGHTSOURCE_UNKNOWN; + image->calibration_illuminant2 = LIGHTSOURCE_UNKNOWN; + + image->white_level[0] = -1; // White level will be set after parsing TAG. + // The spec says: The default value for this + // tag is (2 ** BitsPerSample) + // -1 for unsigned integer images, and 1.0 for + // floating point images. + + image->white_level[1] = -1; + image->white_level[2] = -1; + image->white_level[3] = -1; + image->black_level[0] = 0; + image->black_level[1] = 0; + image->black_level[2] = 0; + image->black_level[3] = 0; + + image->bits_per_sample = 0; + + image->has_active_area = false; + image->active_area[0] = -1; + image->active_area[1] = -1; + image->active_area[2] = -1; + image->active_area[3] = -1; + + image->cfa_plane_color[0] = 0; + image->cfa_plane_color[1] = 1; + image->cfa_plane_color[2] = 2; + image->cfa_plane_color[3] = 0; // optional? + + image->cfa_pattern_dim = 2; + + // The spec says default is None, thus fill with -1(=invalid). + image->cfa_pattern[0][0] = -1; + image->cfa_pattern[0][1] = -1; + image->cfa_pattern[1][0] = -1; + image->cfa_pattern[1][1] = -1; + + image->cfa_layout = 1; + + image->offset = 0; + + image->tile_width = -1; + image->tile_length = -1; + image->tile_offset = 0; + + image->planar_configuration = 1; // chunky + + image->predictor = 1; // no prediction scheme + + image->has_analog_balance = false; + image->has_as_shot_neutral = false; + + image->jpeg_byte_count = -1; + image->strip_byte_count = -1; + + image->samples_per_pixel = 1; + image->rows_per_strip = -1; // 2^32 - 1 + image->bits_per_sample_original = -1; + + image->sample_format = SAMPLEFORMAT_UINT; + + image->compression = COMPRESSION_NONE; + + image->orientation = 1; + + image->strips_per_image = -1; // 2^32 - 1 + + // CR2 specific + image->cr2_slices[0] = 0; + image->cr2_slices[1] = 0; + image->cr2_slices[2] = 0; +} + +// Check if JPEG data is lossless JPEG or not(baseline JPEG) +static bool IsLosslessJPEG(const uint8_t* header_addr, int data_len, int* width, + int* height, int* bits, int* components) { + TINY_DNG_DPRINTF("islossless jpeg\n"); + int lj_width = 0; + int lj_height = 0; + int lj_bits = 0; + lj92 ljp; + int ret = + lj92_open(&ljp, header_addr, data_len, &lj_width, &lj_height, &lj_bits); + if (ret == LJ92_ERROR_NONE) { + // TINY_DNG_DPRINTF("w = %d, h = %d, bits = %d, components = %d\n", + // lj_width, + // lj_height, lj_bits, ljp->components); + + if ((lj_width == 0) || (lj_height == 0) || (lj_bits == 0) || + (lj_bits == 8)) { + // Looks like baseline JPEG + lj92_close(ljp); + return false; + } + + if (components) (*components) = ljp->components; + + lj92_close(ljp); + + if (width) (*width) = lj_width; + if (height) (*height) = lj_height; + if (bits) (*bits) = lj_bits; + } + return (ret == LJ92_ERROR_NONE) ? true : false; +} + +#ifdef TINY_DNG_LOADER_ENABLE_ZIP + +static bool DecompressZIP(unsigned char* dst, + unsigned long* uncompressed_size /* inout */, + const unsigned char* src, unsigned long src_size, + std::string* err) { + std::vector<unsigned char> tmpBuf(*uncompressed_size); + +#ifdef TINY_DNG_LOADER_USE_SYSTEM_ZLIB + int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); + if (Z_OK != ret) { + if (err) { + std::stringstream ss; + ss << "zlib uncompress failed. code = " << ret << "\n"; + (*err) += ss.str(); + } + return false; + } +#else + int ret = mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); + if (MZ_OK != ret) { + if (err) { + std::stringstream ss; + ss << "mz_uncompress failed. code = " << ret << "\n"; + (*err) += ss.str(); + } + return false; + } +#endif + + memcpy(dst, tmpBuf.data(), (*uncompressed_size)); + + return true; +} + +// Assume T = uint8 or uint16 +static bool UnpredictImageU8(std::vector<uint8_t>& dst, // inout + int predictor, const size_t width, + const size_t rows, const size_t spp) { + if (predictor == 1) { + // no prediction shceme + return true; + } else if (predictor == 2) { + // horizontal diff + const size_t stride = size_t(width * spp); + for (size_t row = 0; row < rows; row++) { + for (size_t c = 0; c < spp; c++) { + unsigned int b = dst[row * stride + c]; + for (size_t col = 1; col < width; col++) { + // value may overflow(wrap over), but its expected behavior. + b += dst[stride * row + spp * col + c]; + dst[stride * row + spp * col + c] = + static_cast<unsigned char>(b & 0xFF); + } + } + } + return true; + } else { + // TODO + return false; + } +} + +static bool DecompressZIPedTile(const StreamReader& sr, unsigned char* dst_data, + int dst_width, const DNGImage& image_info, + std::string* err) { + unsigned int tiff_h = 0, tiff_w = 0; + int offset = 0; + + (void)dst_data; + (void)dst_width; + +#ifdef TINY_DNG_LOADER_PROFILING + auto start_t = std::chrono::system_clock::now(); +#endif + + TINY_DNG_DPRINTF("tile_offset = %d\n", int(image_info.tile_offset)); + + if ((image_info.tile_width > 0) && (image_info.tile_length > 0)) { + // Assume ZIP is stored in tiled format. + //TINY_DNG_ASSERT(image_info.tile_width > 0, "Invalid tile width."); + //TINY_DNG_ASSERT(image_info.tile_length > 0, "Invalid tile length."); + + // <- image width(skip len) -> + // +-----------------------------------------+ + // | | + // | <- tile w -> | + // | +-----------+ | + // | | | \ | + // | | | | | + // | | | | tile h | + // | | | | | + // | | | / | + // | +-----------+ | + // | | + // | | + // +-----------------------------------------+ + + TINY_DNG_DPRINTF("tile = %d, %d\n", image_info.tile_width, + image_info.tile_length); + TINY_DNG_DPRINTF("w, h = %d, %d\n", image_info.width, image_info.height); + + // Currently we only support tile data for tile.length == tiff.height. + // assert(image_info.tile_length == image_info.height); + + size_t column_step = 0; // debug + (void)column_step; + + while (tiff_h < static_cast<unsigned int>(image_info.height)) { + TINY_DNG_DPRINTF("sr tell = %d\n", int(sr.tell())); + + if ((image_info.width <= image_info.tile_width) && + (image_info.height <= image_info.tile_length)) { + // Only 1 tile in the image and tile size is larger than image size. + // Use image_info.tile_offset + // FIXME(syoyo): Record tag len in somewhere and lookup it to count the + // number of tiles in the image. + offset = int(image_info.tile_offset); + } else { + // Read offset to data location. + if (!sr.read4(&offset)) { + if (err) { + (*err) += + "Failed to read offset to image data location in " + "DecompressZip.\n"; + } + return false; + } + TINY_DNG_DPRINTF("offt = %d\n", offset); + } + + size_t input_len = sr.size() - static_cast<size_t>(offset); + unsigned long uncompressed_size = + static_cast<unsigned long>( + image_info.samples_per_pixel * image_info.tile_width * + image_info.tile_length * image_info.bits_per_sample) / + static_cast<unsigned long>(8); + + std::vector<uint8_t> tmp_buf; + tmp_buf.resize(uncompressed_size); + + if (!DecompressZIP(tmp_buf.data(), &uncompressed_size, sr.data() + offset, + static_cast<unsigned long>(input_len), err)) { + if (err) { + (*err) += "Failed to decode ZIP data.\n"; + } + return false; + } + + if (!UnpredictImageU8(tmp_buf, image_info.predictor, + size_t(image_info.tile_width), + size_t(image_info.tile_length), + size_t(image_info.samples_per_pixel))) { + if (err) { + (*err) += "Failed to unpredict ZIP-ed tile image.\n"; + } + return false; + } + + // Copy to dest buffer. + // NOTE: For some DNG file, tiled image may exceed the extent of target + // image resolution. + const size_t spp = size_t(image_info.samples_per_pixel); + + for (unsigned int y = 0; + y < static_cast<unsigned int>(image_info.tile_length); y++) { + unsigned int y_offset = y + tiff_h; + if (y_offset >= static_cast<unsigned int>(image_info.height)) { + continue; + } + + size_t dst_offset = + tiff_w + static_cast<unsigned int>(dst_width) * y_offset; + + size_t x_len = static_cast<size_t>(image_info.tile_width); + if ((tiff_w + static_cast<unsigned int>(image_info.tile_width)) >= + static_cast<unsigned int>(dst_width)) { + x_len = static_cast<size_t>(dst_width) - tiff_w; + } + + for (size_t x = 0; x < x_len; x++) { + for (size_t c = 0; c < spp; c++) { + dst_data[spp * (dst_offset + x) + c] = + tmp_buf[spp * (y * static_cast<size_t>(image_info.tile_width) + + x) + + c]; + } + } + } + + tiff_w += static_cast<unsigned int>(image_info.tile_width); + column_step++; + // TINY_DNG_DPRINTF("col = %d, tiff_w = %d / %d\n", column_step, tiff_w, + // image_info.width); + if (tiff_w >= static_cast<unsigned int>(image_info.width)) { + // tiff_h += static_cast<unsigned int>(image_info.tile_length); + tiff_h += static_cast<unsigned int>(image_info.tile_length); + // TINY_DNG_DPRINTF("tiff_h = %d\n", tiff_h); + tiff_w = 0; + column_step = 0; + } + } + } else { + // Assume ZIP data is not stored in tiled format. + + TINY_DNG_DPRINTF("width = %d", int(image_info.width)); + TINY_DNG_DPRINTF("height = %d", int(image_info.height)); + + TINY_DNG_CHECK_AND_RETURN(image_info.offset > 0, "Invalid ZIPed data offset.", err); + offset = static_cast<int>(image_info.offset); + + size_t input_len = sr.size() - static_cast<size_t>(offset); + unsigned long uncompressed_size = + static_cast<unsigned long>(image_info.samples_per_pixel * + image_info.width * image_info.height * + image_info.bits_per_sample) / + static_cast<unsigned long>(8); + + std::vector<uint8_t> tmp_buf; + tmp_buf.resize(uncompressed_size); + + if (!DecompressZIP(tmp_buf.data(), &uncompressed_size, sr.data() + offset, + static_cast<unsigned long>(input_len), err)) { + if (err) { + (*err) += "Failed to decode non-tiled ZIP data.\n"; + } + return false; + } + + if (!UnpredictImageU8(tmp_buf, image_info.predictor, + size_t(image_info.tile_width), + size_t(image_info.tile_length), + size_t(image_info.samples_per_pixel))) { + if (err) { + (*err) += "Failed to unpredict ZIP-ed tile image.\n"; + } + return false; + } + + memcpy(dst_data, tmp_buf.data(), tmp_buf.size()); + } + +#ifdef TINY_DNG_LOADER_PROFILING + auto end_t = std::chrono::system_clock::now(); + auto ms = + std::chrono::duration_cast<std::chrono::milliseconds>(end_t - start_t); + + std::cout << "DecompressZIP : " << ms.count() << " [ms]" << std::endl; +#endif + + return true; +} +#endif + +// Decompress LosslesJPEG adta. +static bool DecompressLosslessJPEG(const StreamReader& sr, + unsigned short* dst_data, int dst_width, + const DNGImage& image_info, int* ljbits_out, + std::string* err) { + unsigned int tiff_h = 0, tiff_w = 0; + int offset = 0; + +#ifdef TINY_DNG_LOADER_PROFILING + auto start_t = std::chrono::system_clock::now(); +#endif + + TINY_DNG_DPRINTF("tile_width %d, tile_length %d\n", image_info.tile_width, + image_info.tile_length); + + if ((image_info.tile_width > 0) && (image_info.tile_length > 0)) { + // Assume Lossless JPEG data is stored in tiled format. + if (image_info.tile_width <= 0) { + if (err) { + (*err) += "Invalid tile width.\n"; + } + return false; + } + if (image_info.tile_length <= 0) { + if (err) { + (*err) += "Invalid tile length.\n"; + } + return false; + } + //TINY_DNG_ASSERT(image_info.tile_width > 0, "Invalid tile width."); + //TINY_DNG_ASSERT(image_info.tile_length > 0, "Invalid tile length."); + + // <- image width(skip len) -> + // +-----------------------------------------+ + // | | + // | <- tile w -> | + // | +-----------+ | + // | | | \ | + // | | | | | + // | | | | tile h | + // | | | | | + // | | | / | + // | +-----------+ | + // | | + // | | + // +-----------------------------------------+ + + // TINY_DNG_DPRINTF("tile = %d, %d\n", image_info.tile_width, + // image_info.tile_length); + + // Currently we only support tile data for tile.length == tiff.height. + // assert(image_info.tile_length == image_info.height); + + size_t column_step = 0; // debug + (void)column_step; + + while (tiff_h < static_cast<unsigned int>(image_info.height)) { + // Read offset to JPEG data location. + if (!sr.read4(&offset)) { + if (err) { + (*err) += + "Failed to read offset to JPEG data location in " + "DecompressLosslessJPEG.\n"; + } + return false; + } + TINY_DNG_DPRINTF("tile offt = %d\n", offset); + + int lj_width = 0; + int lj_height = 0; + int lj_bits = 0; + + lj92 ljp; + + size_t input_len = sr.size() - static_cast<size_t>(offset); + + // @fixme { Parse LJPEG header first and set exact compressed LJPEG data + // length to `data_len` arg. } + int ret = + lj92_open(&ljp, reinterpret_cast<const uint8_t*>(sr.data() + offset), + /* data_len */ static_cast<int>(input_len), &lj_width, + &lj_height, &lj_bits); + TINY_DNG_DPRINTF("ret = %d\n", ret); + TINY_DNG_CHECK_AND_RETURN(ret == LJ92_ERROR_NONE, "Error opening JPEG stream.", err); + + TINY_DNG_DPRINTF("lj %d, %d, %d\n", lj_width, lj_height, lj_bits); + TINY_DNG_DPRINTF("ljp x %d, y %d, c %d\n", ljp->x, ljp->y, + ljp->components); + TINY_DNG_DPRINTF("tile width = %d\n", image_info.tile_width); + TINY_DNG_DPRINTF("tile height = %d\n", image_info.tile_length); + TINY_DNG_DPRINTF("col = %d, tiff_w = %d / %d\n", int(column_step), tiff_w, + image_info.width); + + TINY_DNG_CHECK_AND_RETURN(lj_width <= image_info.tile_width, "Unexpected JPEG tile width size.", err); + TINY_DNG_CHECK_AND_RETURN(lj_height <= image_info.tile_length, "Unexpected JPEG tile length size.", err); + + //TINY_DNG_ASSERT((lj_width * lj_height) == + // image_info.tile_width * image_info.tile_length, + // "Unexpected JPEG tile size."); + + TINY_DNG_DPRINTF("lj.components %d, samples_per_pixel %d\n", ljp->components, image_info.samples_per_pixel); + //TINY_DNG_ASSERT(ljp->components == image_info.samples_per_pixel, + // "# of color channels does not match."); + + // int write_length = image_info.tile_width; + // int skip_length = dst_width - image_info.tile_width; + // TINY_DNG_DPRINTF("write_len = %d, skip_len = %d\n", write_length, + // skip_length); + + // size_t dst_offset = + // column_step * static_cast<size_t>(image_info.tile_width) + + // static_cast<unsigned int>(dst_width) * tiff_h; + + // Decode into temporary buffer. + + std::vector<uint16_t> tmpbuf; + tmpbuf.resize( + static_cast<size_t>(lj_width * lj_height * ljp->components)); + + // TODO: ljp->components > image_info.samples_per_pixel + ret = lj92_decode(ljp, tmpbuf.data(), image_info.tile_width, 0, NULL, 0); + // ret = lj92_decode(ljp, tmpbuf.data(), write_length, skip_length, NULL, + // 0); + TINY_DNG_CHECK_AND_RETURN(ret == LJ92_ERROR_NONE, "Error decoding JPEG stream.", err); + // ret = lj92_decode(ljp, dst_data + dst_offset, write_length, + // skip_length, + // NULL, 0); + + // Copy to dest buffer. + // NOTE: For some DNG file, tiled image may exceed the extent of target + // image resolution. + +#if 0 // TODO: remove + for (unsigned int y = 0; + y < static_cast<unsigned int>(image_info.tile_length); y++) { + unsigned int y_offset = y + tiff_h; + if (y_offset >= static_cast<unsigned int>(image_info.height)) { + continue; + } + + size_t dst_offset = + tiff_w + static_cast<unsigned int>(dst_width) * y_offset; + + size_t x_len = static_cast<size_t>(image_info.tile_width); + if ((tiff_w + static_cast<unsigned int>(image_info.tile_width)) >= + static_cast<unsigned int>(dst_width)) { + x_len = static_cast<size_t>(dst_width) - tiff_w; + } + for (size_t x = 0; x < x_len; x++) { + dst_data[dst_offset + x] = + tmpbuf[y * static_cast<size_t>(image_info.tile_width) + x]; + } + } +#endif + + const size_t spp = size_t(image_info.samples_per_pixel); + + // const size_t tile_size = + // size_t(image_info.tile_width) * size_t(image_info.tile_length); + for (unsigned int y = 0; + y < static_cast<unsigned int>(image_info.tile_length); y++) { + unsigned int y_offset = y + tiff_h; + if (y_offset >= static_cast<unsigned int>(image_info.height)) { + continue; + } + + size_t dst_offset = + tiff_w + static_cast<unsigned int>(dst_width) * y_offset; + + size_t x_len = static_cast<size_t>(image_info.tile_width); + if ((tiff_w + static_cast<unsigned int>(image_info.tile_width)) >= + static_cast<unsigned int>(dst_width)) { + x_len = static_cast<size_t>(dst_width) - tiff_w; + } + + // Decoded ljpeg data is already channel first(RGBRGBRGB...) + for (size_t x = 0; x < x_len; x++) { + for (size_t c = 0; c < spp; c++) { + dst_data[spp * (dst_offset + x) + c] = + tmpbuf[spp * (y * static_cast<size_t>(image_info.tile_width) + + x) + + c]; + } + } + } + + TINY_DNG_CHECK_AND_RETURN(ret == LJ92_ERROR_NONE, + "Error opening JPEG stream.", err); // @fixme: redundant? + + if (ljbits_out && (lj_bits > 0)) { + // Assume all tiles have same lj_bits value. + (*ljbits_out) = lj_bits; + } + + lj92_close(ljp); + + tiff_w += static_cast<unsigned int>(image_info.tile_width); + column_step++; + // TINY_DNG_DPRINTF("col = %d, tiff_w = %d / %d\n", column_step, tiff_w, + // image_info.width); + if (tiff_w >= static_cast<unsigned int>(image_info.width)) { + // tiff_h += static_cast<unsigned int>(image_info.tile_length); + tiff_h += static_cast<unsigned int>(image_info.tile_length); + // TINY_DNG_DPRINTF("tiff_h = %d\n", tiff_h); + tiff_w = 0; + column_step = 0; + } + } + } else { + // Assume LJPEG data is not stored in tiled format. + + // Read offset to JPEG data location. + // offset = static_cast<int>(Read4(fp, swap_endian)); + + if (image_info.offset <= 0) { + TINY_DNG_ERROR_AND_RETURN("Invalid JPEG data offset.", err); + } + + offset = static_cast<int>(image_info.offset); + + TINY_DNG_DPRINTF("LJPEG offset %d\n", offset); + + int lj_width = 0; + int lj_height = 0; + int lj_bits = 0; + lj92 ljp; + + size_t input_len = sr.size() - static_cast<size_t>(offset); + + // @fixme { Parse LJPEG header first and set exact compressed LJPEG data + // length to `data_len` arg. } + int ret = + lj92_open(&ljp, reinterpret_cast<const uint8_t*>(sr.data() + offset), + /* data_len */ static_cast<int>(input_len), &lj_width, + &lj_height, &lj_bits); + + // TINY_DNG_DPRINTF("ret = %d\n", ret); + if (ret != LJ92_ERROR_NONE) { + TINY_DNG_ERROR_AND_RETURN("Error opening JPEG stream.", err); + } + + // TINY_DNG_DPRINTF("lj %d, %d, %d\n", lj_width, lj_height, lj_bits); + + int write_length = image_info.width; + int skip_length = 0; + + ret = lj92_decode(ljp, dst_data, write_length, skip_length, NULL, 0); + // TINY_DNG_DPRINTF("ret = %d\n", ret); + + if (ret != LJ92_ERROR_NONE) { + TINY_DNG_ERROR_AND_RETURN("Error decoding JPEG stream.", err); + } + + lj92_close(ljp); + + if (ljbits_out && (lj_bits > 0)) { + (*ljbits_out) = lj_bits; + } + } + +#ifdef TINY_DNG_LOADER_PROFILING + auto end_t = std::chrono::system_clock::now(); + auto ms = + std::chrono::duration_cast<std::chrono::milliseconds>(end_t - start_t); + + std::cout << "DecompressLosslessJPEG : " << ms.count() << " [ms]" + << std::endl; +#endif + + return true; +} + +// Currently we only support parsing GainMap +static bool ParseOpcodeList(unsigned short tag, const uint8_t *data, size_t dataSize, + std::vector<GainMap> *gainmaps_out) +{ + const size_t kMaxSize = 1024*1024*512; + + // OpCode data is always store in big-endian byte order. + // First 32bit uint: The number of opcodes. + // For each opcode: + // 32bit uint for OpCodeID + // 32bit uint for DNG version + // 32bit uint for various flag bits. + // 32bit uint for the number of bytes of opcode data. + // + // Value range of processed Image data after OpCode processing(not implemented in TinyDNG) + // Opcode1 : 0 to 2^32 - 1 + // Opcode2 : 0 to 2^16 - 1 + // Opcode3 : 0.0 to 1.0 + + // TODO: Clip image data range according with `tag` + (void)tag; + + if (dataSize <= (4 * 5)) { + // Too small + return false; + } + + bool swap_endian = !IsBigEndian(); + StreamReader sr(data, dataSize, swap_endian); + + uint32_t num_opcodes = 0; + + if (!sr.read4(&num_opcodes)) { + return false; + } + + const size_t kMaxNumOpcodes = 16; + if (num_opcodes > kMaxNumOpcodes) { + // too many opcodes. + return false; + } + + //TINY_DNG_DPRINTF("# of opcodes = %d\n", num_opcodes); + + for (size_t i = 0; i < num_opcodes; i++) { + uint32_t opcode_id = 0; + uint32_t dng_version = 0; + uint32_t flags = 0; + uint32_t num_bytes = 0; + + if (!sr.read4(&opcode_id)) { + return false; + } + if (!sr.read4(&dng_version)) { + return false; + } + if (!sr.read4(&flags)) { + return false; + } + if (!sr.read4(&num_bytes)) { + return false; + } + + TINY_DNG_DPRINTF("opcode %d, dng ver %d, flags %d, num_bytes %d\n", opcode_id, dng_version, flags, num_bytes); + + if (num_bytes < 4) { + return false; + } + + if (opcode_id == OPCODE_LIST_GAIN_MAP) { + const size_t kMaxItems = 1024*1024; + + uint32_t saved_loc = uint32_t(sr.tell()); + + // Top, Left, Bottom, Right, Plane, Planes, RowPitch, ColPitch, MapPointsV, MapPointsH (LONG) + // MapSpacingV, MapSpacingH, MapOriginV, MapOriginH (DOUBLE) + // MapPlanes (LONG) + // For each MapPointsV + // For each MapPointsH + // For each MapPlanes + // MapGain (FLOAT) + + uint32_t top, left, bottom, right, plane, planes, row_pitch, col_pitch, map_points_v, map_points_h; + double map_spacing_v, map_spacing_h, map_origin_v, map_origin_h; + uint32_t map_planes; + + if (!sr.read4(&top)) { + return false; + } + + if (!sr.read4(&left)) { + return false; + } + + if (!sr.read4(&bottom)) { + return false; + } + + if (!sr.read4(&right)) { + return false; + } + + if (!sr.read4(&plane)) { + return false; + } + + if (!sr.read4(&planes)) { + return false; + } + + if (!sr.read4(&row_pitch)) { + return false; + } + + if (!sr.read4(&col_pitch)) { + return false; + } + + if (!sr.read4(&map_points_v)) { + return false; + } + + if (!sr.read4(&map_points_h)) { + return false; + } + + if (!sr.read_double(&map_spacing_v)) { + return false; + } + + if (!sr.read_double(&map_spacing_h)) { + return false; + } + + if (!sr.read_double(&map_origin_v)) { + return false; + } + + if (!sr.read_double(&map_origin_h)) { + return false; + } + + if (!sr.read4(&map_planes)) { + return false; + } + + size_t num_items = map_points_v * map_points_h * map_planes; + + //TINY_DNG_DPRINTF("top %d, left %d, bottom %d, right %d\n", top, left, bottom, right); + //TINY_DNG_DPRINTF("plane %d, planes %d\n", plane, planes); + //TINY_DNG_DPRINTF("row_pitch %d, col_pitch %d\n", row_pitch, col_pitch); + //TINY_DNG_DPRINTF("map_points_v %d, map_points_h %d\n", map_points_v, map_points_h); + //TINY_DNG_DPRINTF("map_spacing_v %f, map_spacing_h %f\n", map_spacing_v, map_spacing_h); + //TINY_DNG_DPRINTF("map_origin_v %f, map_origin_h %f\n", map_origin_v, map_origin_h); + //TINY_DNG_DPRINTF("map_planes %d\n", map_planes); + //TINY_DNG_DPRINTF("num_items %d\n", int(num_items)); + + // Read gain values. + + if (num_items > kMaxItems) { + return false; + } + + std::vector<float> gainmap_pixels(num_items); + for (size_t k = 0; k < num_items; k++) { + + if (!sr.read_float(&gainmap_pixels[k])) { + return false; + } + + //TINY_DNG_DPRINTF("values = %f\n", double(gainmap_pixels[k])); + } + + GainMap gmap; + gmap.idx = (tag - TAG_OPCODE_LIST1) + 1; + //TINY_DNG_DPRINTF("idx = %d\n", gmap.idx); + gmap.top = top; + gmap.left = left; + gmap.bottom = bottom; + gmap.right = right; + gmap.plane = plane; + gmap.planes = planes; + gmap.row_pitch = row_pitch; + gmap.col_pitch = col_pitch; + gmap.map_points_v = map_points_v; + gmap.map_points_h = map_points_h; + gmap.map_origin_v = map_origin_v; + gmap.map_origin_h = map_origin_h; + gmap.map_spacing_v = map_spacing_v; + gmap.map_spacing_h = map_spacing_h; + gmap.map_planes = map_planes; + gmap.pixels = gainmap_pixels; + + gainmaps_out->push_back(gmap); + + // Go to next OpCode data + // TODO: Ensure read bytes == num_bytes + if (!sr.seek_set(saved_loc + num_bytes)) { + return false; + } + + } else { + + if (num_bytes > kMaxSize) { + // Too large bytes. Guess invalid OpCode data. + return false; + } + + // Unimplemented + std::vector<uint8_t> op_data(num_bytes); + if (!sr.read(num_bytes, num_bytes, reinterpret_cast<unsigned char *>(op_data.data()))) { + return false; + } + + } + + } + + return true; +} + +// Parse custom TIFF field +// returns -1 when error. +// returns 0 when not found. +// returns 1 when success. +static int ParseCustomField(const StreamReader& sr, + const std::vector<FieldInfo>& field_lists, + const unsigned short tag, const unsigned short type, + const unsigned int len, FieldData* data, + std::string* err) { + bool found = false; + + (void)len; + + // Simple linear search. + // TODO(syoyo): Use binary search for faster procesing. + for (size_t i = 0; i < field_lists.size(); i++) { + if ((field_lists[i].tag > TAG_NEW_SUBFILE_TYPE) && + (field_lists[i].tag == tag) && (field_lists[i].type == type)) { + if ((type == TYPE_BYTE) || (type == TYPE_SBYTE)) { + data->name = field_lists[i].name; + data->type = static_cast<DataType>(type); + unsigned char val; + if (!sr.read1(&val)) { + if (err) { + (*err) += "Failed tp parse custom field.\n"; + } + return -1; + } + + data->data.resize(1); + data->data[0] = val; + found = true; + } else if ((type == TYPE_SHORT) || (type == TYPE_SSHORT)) { + data->name = field_lists[i].name; + data->type = static_cast<DataType>(type); + unsigned short val; + if (!sr.read2(&val)) { + if (err) { + (*err) += "Failed tp parse custom field.\n"; + } + return -1; + } + data->data.resize(sizeof(short)); + memcpy(data->data.data(), &val, sizeof(short)); + found = true; + } else if ((type == TYPE_LONG) || (type == TYPE_SLONG) || + (type == TYPE_FLOAT)) { + data->name = field_lists[i].name; + data->type = static_cast<DataType>(type); + unsigned int val; + if (!sr.read4(&val)) { + if (err) { + (*err) += "Failed tp parse custom field.\n"; + } + return -1; + } + data->data.resize(sizeof(int)); + memcpy(data->data.data(), &val, sizeof(int)); + found = true; + } else if ((type == TYPE_RATIONAL) || (type == TYPE_SRATIONAL)) { + data->name = field_lists[i].name; + data->type = static_cast<DataType>(type); + unsigned int num, denom; + + if (!sr.read4(&num)) { + if (err) { + (*err) += "Failed tp parse custom field.\n"; + } + return -1; + } + + if (!sr.read4(&denom)) { + if (err) { + (*err) += "Failed tp parse custom field.\n"; + } + return -1; + } + + data->data.resize(sizeof(int) * 2); + + // Store rational value as is. + memcpy(&data->data[0], &num, 4); + memcpy(&data->data[4], &denom, 4); + found = true; + } else { + // TODO(syoyo): Support more data types. + } + } + } + + return found ? 1 : 0; +} + +// Parse TIFF IFD. +// Returns true upon success, false if failed to parse. +static bool ParseTIFFIFD(const StreamReader& sr, + const std::vector<FieldInfo>& custom_field_lists, + std::vector<tinydng::DNGImage>* images, + std::string* warn, std::string* err, uint32_t call_depth = 0) { + if (!images) { + if (err) { + (*err) += "`images` argument is null.\n"; + } + return false; + } + + tinydng::DNGImage image; + InitializeDNGImage(&image); + + // TINY_DNG_DPRINTF("id = %d\n", idx); + unsigned short num_entries = 0; + if (!sr.read2(&num_entries)) { + if (err) { + (*err) += "Faild to read the number of entries in TIFF IFD.\n"; + } + return false; + } + + if (num_entries == 0) { + if (err) { + (*err) += "TIFF IFD cannot have 0 entries.\n"; + } + return false; + } + + TINY_DNG_DPRINTF("----------\n"); + TINY_DNG_DPRINTF("num entries %d\n", num_entries); + + // For delayed reading of strip offsets and strip byte counts. + long offt_strip_offset = 0; + long offt_strip_byte_counts = 0; + + while (num_entries--) { + unsigned short tag, type; + unsigned int len; + unsigned int saved_offt; + if (!GetTIFFTag(sr, &tag, &type, &len, &saved_offt)) { + if (err) { + (*err) += "Failed to read TIFF Tag.\n"; + } + return false; + } + + TINY_DNG_DPRINTF("tag %d\n", tag); + TINY_DNG_DPRINTF("saved_offt %d\n", saved_offt); + if (tag < TAG_NEW_SUBFILE_TYPE) { + if (err) { + (*err) += "Invalid tag ID.\n"; + } + return false; + } + + // TINY_DNG_DPRINTF("tag = %d\n", tag); + + switch (tag) { + case 2: + case TAG_IMAGE_WIDTH: + case 61441: // ImageWidth + if (!sr.read_uint(type, + reinterpret_cast<unsigned int*>(&(image.width)))) { + if (err) { + (*err) += "Failed to read ImageWidth Tag.\n"; + } + return false; + } + // TINY_DNG_DPRINTF("[%d] width = %d\n", idx, info.width); + break; + + case 3: + case TAG_IMAGE_HEIGHT: + case 61442: // ImageHeight + if (!sr.read_uint(type, + reinterpret_cast<unsigned int*>(&(image.height)))) { + if (err) { + (*err) += "Failed to read ImageHeight Tag.\n"; + } + return false; + } + // TINY_DNG_DPRINTF("height = %d\n", image.height); + break; + + case TAG_BITS_PER_SAMPLE: + case 61443: // BitsPerSample + // image->samples = len & 7; + if (!sr.read_uint(type, reinterpret_cast<unsigned int*>( + &(image.bits_per_sample_original)))) { + if (err) { + (*err) += "Failed to read BitsPerSample Tag.\n"; + } + return false; + } + break; + + case TAG_SAMPLES_PER_PIXEL: { + short spp = 0; + if (!sr.read2(&spp)) { + if (err) { + (*err) += "Failed to read SamplesPerPixel Tag.\n"; + } + return false; + } + + if (spp < 1) { + if (err) { + (*err) += "SamplesPerPixel must be 1 ~ 4, but got " + std::to_string(spp) + ".\n"; + } + return false; + } + + if (spp > 4) { + if (err) { + (*err) += "SamplesPerPixel must be less than or equal to 4.\n"; + } + return false; + } + + image.samples_per_pixel = static_cast<int>(spp); + + // TINY_DNG_DPRINTF("spp = %d\n", image.samples_per_pixel); + } break; + + case TAG_ROWS_PER_STRIP: { + // The TIFF Spec says data type may be SHORT, but assume LONG for a + // while. + if (!sr.read4(&image.rows_per_strip)) { + if (err) { + (*err) += "Failed to parse RowsPerStrip Tag.\n"; + } + return false; + } + // NOTE: Compute strip_per_image in later since image.height is required + // to compute strips_per_image. + } break; + + case TAG_COMPRESSION: + if (!sr.read_uint( + type, reinterpret_cast<unsigned int*>(&image.compression))) { + if (err) { + (*err) += "Failed to parse Compression Tag.\n"; + } + return false; + } + + // TINY_DNG_DPRINTF("tag-compression = %d\n", image.compression); + break; + + case TAG_STRIP_OFFSET: + case TAG_JPEG_IF_OFFSET: + offt_strip_offset = static_cast<long>(sr.tell()); + if (!sr.read4(&image.offset)) { + if (err) { + (*err) += "Failed to parse Compression Tag.\n"; + } + return false; + } + // TINY_DNG_DPRINTF("strip_offset = %d\n", image.offset); + break; + + case TAG_JPEG_IF_BYTE_COUNT: + if (!sr.read4(&image.jpeg_byte_count)) { + if (err) { + (*err) = "Failed to parse JpegIfByteCount Tag.\n"; + } + return false; + } + break; + + case TAG_ORIENTATION: + if (!sr.read2(&image.orientation)) { + if (err) { + (*err) = "Failed to parse Orientation Tag.\n"; + } + return false; + } + break; + + case TAG_STRIP_BYTE_COUNTS: + offt_strip_byte_counts = static_cast<long>(sr.tell()); + if (!sr.read4(&image.strip_byte_count)) { + if (err) { + (*err) = "Failed to parse StripByteCount Tag.\n"; + } + return false; + } + TINY_DNG_DPRINTF("strip_byte_count = %d\n", image.strip_byte_count); + break; + + case TAG_PLANAR_CONFIGURATION: + if (!sr.read2(&image.planar_configuration)) { + if (err) { + (*err) = "Failed to parse PlanarConfiguration Tag.\n"; + } + return false; + } + break; + + case TAG_PREDICTOR: + if (!sr.read2(&image.predictor)) { + if (err) { + (*err) = "Failed to parse Predictor Tag.\n"; + } + return false; + } + + if ((image.predictor < 1) || (image.predictor > 3)) { + if (err) { + (*err) = "Predictor value must be 1, 2 or 3.\n"; + } + return false; + } + break; + + case TAG_SAMPLE_FORMAT: { + short format; + if (!sr.read2(&format)) { + if (err) { + (*err) = "Failed to parse SampleFormat.\n"; + } + return false; + } + + if ((format == SAMPLEFORMAT_INT) || (format == SAMPLEFORMAT_UINT) || + (format == SAMPLEFORMAT_IEEEFP)) { + image.sample_format = static_cast<SampleFormat>(format); + } + } break; + + case TAG_SUB_IFDS: + + { + // TINY_DNG_DPRINTF("sub_ifds = %d\n", len); + for (size_t k = 0; k < len; k++) { + unsigned int i = static_cast<unsigned int>(sr.tell()); + unsigned int offt; + if (!sr.read4(&offt)) { + if (err) { + (*err) += "Failed to parse SubIFDs Tag.\n"; + } + return false; + } + + unsigned int base = 0; // @fixme + if (!sr.seek_set(offt + base)) { + if (err) { + (*err) += "Failed to seek to SubIFD Tag.\n"; + } + return false; + } + + // recursive call + if (call_depth > kMaxRecursiveIFDParse) { + if (err) { + (*err) += "Too many nested SUB_IFDS. Input DNG seems invalid or malcious.\n"; + } + return false; + } + + if (!ParseTIFFIFD(sr, custom_field_lists, images, warn, err, call_depth+1)) { + if (err) { + (*err) += "Failed to Parse SubIFD Tag.\n"; + } + return false; + } + + if (!sr.seek_set(i + 4)) { + if (err) { + (*err) += "Failed to rewind to SubIFD Tag position.\n"; + } + return false; + } + } + // TINY_DNG_DPRINTF("sub_ifds DONE\n"); + } + + break; + + case TAG_TILE_WIDTH: + if (!sr.read_uint(type, + reinterpret_cast<unsigned int*>(&image.tile_width))) { + if (err) { + (*err) += "Failed to parse TileWidth Tag.\n"; + } + } + // TINY_DNG_DPRINTF("tile_width = %d\n", image.tile_width); + break; + + case TAG_TILE_LENGTH: + // TINY_DNG_DPRINTF("tile_length = %d\n", image.tile_length); + if (!sr.read_uint( + type, reinterpret_cast<unsigned int*>(&image.tile_length))) { + if (err) { + (*err) += "Failed to parse TileLength Tag.\n"; + } + } + break; + + case TAG_TILE_OFFSETS: + if (len > 1) { + image.tile_offset = static_cast<unsigned int>(sr.tell()); + } else { + if (!sr.read4(&image.tile_offset)) { + if (err) { + (*err) += "Failed to parse TileOffsets Tag.\n"; + } + } + } + TINY_DNG_DPRINTF("tile_offt = %d\n", int(image.tile_offset)); + break; + + case TAG_TILE_BYTE_COUNTS: + if (len > 1) { + image.tile_byte_count = static_cast<unsigned int>(sr.tell()); + } else { + if (!sr.read4(&image.tile_byte_count)) { + if (err) { + (*err) += "Failed to parse TileByteCounts Tag.\n"; + } + } + } + break; + + case TAG_CFA_PATTERN_DIM: + if (!sr.read2(&image.cfa_pattern_dim)) { + if (err) { + (*err) = "Failed to parse CFA PatternDim Tag.\n"; + } + return false; + } + break; + + case TAG_CFA_PATTERN: { + char buf[16]; + size_t readLen = len; + if (readLen > 16) readLen = 16; + + if (!sr.read(readLen, 16, reinterpret_cast<unsigned char*>(buf))) { + if (err) { + (*err) = "Failed to parse CFA Pattern Tag.\n"; + } + return false; + } + + // Only 2x2 CFAPattern is supported at the moment. + if (readLen == 4) { + image.cfa_pattern[0][0] = buf[0]; + image.cfa_pattern[0][1] = buf[1]; + image.cfa_pattern[1][0] = buf[2]; + image.cfa_pattern[1][1] = buf[3]; + } else { + if (err) { + (*err) = + "Length of CFA pattern other than 4(2x2) is not supported " + "yet.\n"; + } + return false; + } + } break; + + case TAG_DNG_VERSION: { + char data[4]; + { + for (int i = 0; i < 4; i++) { + if (!sr.read1(&data[i])) { + if (err) { + (*err) += "Failed to parse DNGVersion Tag.\n"; + } + return false; + } + } + } + + image.version = + (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; + } break; + + case TAG_CFA_PLANE_COLOR: { + char buf[4]; + size_t readLen = len; + if (readLen > 4) readLen = 4; + + if (!sr.read(readLen, readLen, reinterpret_cast<unsigned char*>(buf))) { + if (err) { + (*err) += "Failed to parse CFALayout Tag.\n"; + } + return false; + } + + for (size_t i = 0; i < readLen; i++) { + image.cfa_plane_color[i] = buf[i]; + } + } break; + + case TAG_CFA_LAYOUT: { + if (!sr.read4(&image.cfa_layout)) { + if (err) { + (*err) += "Failed to parse CFALayout Tag.\n"; + } + return false; + } + } break; + + case TAG_ACTIVE_AREA: + + for (size_t c = 0; c < 4; c++) { + if (!sr.read_uint(type, reinterpret_cast<unsigned int*>( + &image.active_area[c]))) { + if (err) { + (*err) += "Failed to parse ActiveArea Tag.\n"; + } + return false; + } + } + + image.has_active_area = true; + + break; + + case TAG_BLACK_LEVEL: { + // Assume TAG_SAMPLES_PER_PIXEL is read before + // FIXME(syoyo): scan TAG_SAMPLES_PER_PIXEL in IFD table in advance. + for (int s = 0; s < image.samples_per_pixel; s++) { + if (!sr.read_uint(type, reinterpret_cast<unsigned int*>( + &image.black_level[s]))) { + if (err) { + (*err) += "Failed to parse BlackLevel Tag.\n"; + } + return false; + } + } + } break; + + case TAG_WHITE_LEVEL: { + // Assume TAG_SAMPLES_PER_PIXEL is read before + // FIXME(syoyo): scan TAG_SAMPLES_PER_PIXEL in IFD table in advance. + for (int s = 0; s < image.samples_per_pixel; s++) { + if (!sr.read_uint(type, reinterpret_cast<unsigned int*>( + &image.white_level[s]))) { + if (err) { + (*err) += "Failed to parse WhiteLevel Tag.\n"; + } + return false; + } + } + } break; + + case TAG_ANALOG_BALANCE: + // Assume RGB + if (!sr.read_real(type, &image.analog_balance[0])) { + if (err) { + (*err) += "Failed to parse analog balance.\n"; + } + return false; + } + if (!sr.read_real(type, &image.analog_balance[1])) { + if (err) { + (*err) += "Failed to parse analog balance.\n"; + } + return false; + } + if (!sr.read_real(type, &image.analog_balance[2])) { + if (err) { + (*err) += "Failed to parse analog balance.\n"; + } + return false; + } + + image.has_analog_balance = true; + break; + + case TAG_AS_SHOT_NEUTRAL: + // Assume RGB + // TINY_DNG_DPRINTF("ty = %d\n", type); + for (size_t c = 0; c < 3; c++) { + if (!sr.read_real(type, &image.as_shot_neutral[c])) { + if (err) { + (*err) += "Failed to parse AsShotNeutral Tag.\n"; + } + return false; + } + } + + image.has_as_shot_neutral = true; + break; + + case TAG_CALIBRATION_ILLUMINANT1: { + unsigned short val; + if (!sr.read2(&val)) { + if (err) { + (*err) += "Failed to parse CalibrartionIlluminant1 Tag.\n"; + } + return false; + } + + image.calibration_illuminant1 = static_cast<LightSource>(val); + } break; + + case TAG_CALIBRATION_ILLUMINANT2: { + unsigned short val; + if (!sr.read2(&val)) { + if (err) { + (*err) += "Failed to parse CalibrartionIlluminant2 Tag.\n"; + } + return false; + } + image.calibration_illuminant2 = static_cast<LightSource>(val); + } break; + + case TAG_COLOR_MATRIX1: { + for (int c = 0; c < 3; c++) { + for (int k = 0; k < 3; k++) { + double val; + if (!sr.read_real(type, &val)) { + if (err) { + (*err) += "Failed to parse ColorMatrix1 Tag.\n"; + } + return false; + } + + image.color_matrix1[c][k] = val; + } + } + } break; + + case TAG_COLOR_MATRIX2: { + for (int c = 0; c < 3; c++) { + for (int k = 0; k < 3; k++) { + double val; + if (!sr.read_real(type, &val)) { + if (err) { + (*err) += "Failed to parse ColorMatrix2 Tag.\n"; + } + return false; + } + image.color_matrix2[c][k] = val; + } + } + } break; + + case TAG_FORWARD_MATRIX1: { + for (int c = 0; c < 3; c++) { + for (int k = 0; k < 3; k++) { + double val; + if (!sr.read_real(type, &val)) { + if (err) { + (*err) += "Failed to parse ForwardMatrix1 Tag.\n"; + } + return false; + } + image.forward_matrix1[c][k] = val; + } + } + } break; + + case TAG_FORWARD_MATRIX2: { + for (int c = 0; c < 3; c++) { + for (int k = 0; k < 3; k++) { + double val; + if (!sr.read_real(type, &val)) { + if (err) { + (*err) += "Failed to parse ForwardMatrix2 Tag.\n"; + } + return false; + } + image.forward_matrix2[c][k] = val; + } + } + } break; + + case TAG_CAMERA_CALIBRATION1: { + for (int c = 0; c < 3; c++) { + for (int k = 0; k < 3; k++) { + double val; + if (!sr.read_real(type, &val)) { + if (err) { + (*err) += "Failed to parse CameraCalibration1 Tag.\n"; + } + return false; + } + image.camera_calibration1[c][k] = val; + } + } + } break; + + case TAG_CAMERA_CALIBRATION2: { + for (int c = 0; c < 3; c++) { + for (int k = 0; k < 3; k++) { + double val; + if (!sr.read_real(type, &val)) { + if (err) { + (*err) += "Failed to parse CameraCalibration2 Tag.\n"; + } + return false; + } + image.camera_calibration2[c][k] = val; + } + } + } break; + + case TAG_CR2_SLICES: { + // Assume 3 ushorts; + for (size_t c = 0; c < 3; c++) { + if (!sr.read2(&image.cr2_slices[c])) { + if (err) { + (*err) += "Failed to parse CR2Slices Tag.\n"; + } + return false; + } + } + // TINY_DNG_DPRINTF("cr2_slices = %d, %d, %d\n", + // image.cr2_slices[0], + // image.cr2_slices[1], + // image.cr2_slices[2]); + } break; + + case TAG_SEMANTIC_NAME: { + size_t readLen = len; + if (readLen < 1) { + if (err) { + (*err) += "Null string for SemanticName Tag.\n"; + } + + return false; + } + + const size_t kMaxNameSize = 1024 * 1024; + + if (readLen > kMaxNameSize) { + if (err) { + (*err) += "The length of SemanticName string too large.\n"; + } + return false; + } + + std::vector<uint8_t> buf(readLen); // readLen includes null char + if (!sr.read(readLen, readLen, + reinterpret_cast<unsigned char*>(buf.data()))) { + if (err) { + (*err) += "Failed to parse SemanticName Tag.\n"; + } + return false; + } + + image.semantic_name = std::string(buf.begin(), buf.end()); + + TINY_DNG_DPRINTF("semantic_name = %s\n", image.semantic_name.c_str()); + } break; + + case TAG_OPCODE_LIST1: + case TAG_OPCODE_LIST2: + case TAG_OPCODE_LIST3: { + const size_t kMaxOpcodeDataSize = 1024*1024*256; + + TINY_DNG_DPRINTF("opcodelist %d\n", tag); + size_t readLen = len; + if (readLen < 1) { + if (err) { + (*err) += "Empty data for OpCodeList Tag.\n"; + } + + return false; + } + + if (readLen > kMaxOpcodeDataSize) { + if (err) { + (*err) += "OpCodeList data too large.\n"; + } + + return false; + } + std::vector<uint8_t> buf(readLen); + if (!sr.read(readLen, readLen, + reinterpret_cast<unsigned char*>(buf.data()))) { + if (err) { + (*err) += "Failed to read OpCodeList data.\n"; + } + return false; + } + + std::vector<GainMap> *gainmaps = NULL; + if (tag == TAG_OPCODE_LIST1) { + gainmaps = &image.opcodelist1_gainmap; + } else if (tag == TAG_OPCODE_LIST2) { + gainmaps = &image.opcodelist2_gainmap; + } else if (tag == TAG_OPCODE_LIST3) { + gainmaps = &image.opcodelist3_gainmap; + } + + if (!ParseOpcodeList(tag, buf.data(), buf.size(), gainmaps)) { + if (err) { + (*err) += "Failed to parse OpCodeList Tag.\n"; + } + return false; + } + + TINY_DNG_DPRINTF("opcodelist %d, dataLen = %d\n", tag, int(readLen)); + + } break; + + default: { + FieldData data; + int ret = ParseCustomField(sr, custom_field_lists, tag, type, len, + &data, err); + if (ret == -1) { + return false; + } + + if (ret > 0) { + image.custom_fields.push_back(data); + } + // TINY_DNG_DPRINTF("unknown or unsupported tag = %d\n", tag); + } + } + + sr.seek_set(saved_offt); + } + + if (image.rows_per_strip > 0) { + if (image.height == -1) { + if (err) { + (*err) = "image height tag is required to compute StripsPerImage.\n"; + } + return false; + } + + // http://www.awaresystems.be/imaging/tiff/tifftags/rowsperstrip.html + image.strips_per_image = + static_cast<int>(floor(double(image.height + image.rows_per_strip - 1) / + double(image.rows_per_strip))); + TINY_DNG_DPRINTF("rows_per_strip = %d\n", image.samples_per_pixel); + TINY_DNG_DPRINTF("strips_per_image = %d\n", image.strips_per_image); + } + + // Delayed read of strip offsets and strip byte counts + if (image.strips_per_image > 0) { + image.strip_byte_counts.clear(); + image.strip_offsets.clear(); + + long curr_offt = static_cast<long>(sr.tell()); + + if (offt_strip_byte_counts > 0) { + if (!sr.seek_set(uint64_t(offt_strip_byte_counts))) { + if (err) { + (*err) = "Failed to seek.\n"; + } + return false; + } + + for (int k = 0; k < image.strips_per_image; k++) { + unsigned int strip_byte_count; + if (!sr.read4(&strip_byte_count)) { + if (err) { + (*err) += "Failed to read StripByteCount value."; + } + return false; + } + TINY_DNG_DPRINTF("strip_byte_counts[%d] = %u\n", k, strip_byte_count); + image.strip_byte_counts.push_back(strip_byte_count); + } + } + + if (offt_strip_offset > 0) { + if (!sr.seek_set(uint64_t(offt_strip_offset))) { + if (err) { + (*err) = "Failed to seek.\n"; + } + return false; + } + + for (int k = 0; k < image.strips_per_image; k++) { + unsigned int strip_offset; + if (!sr.read4(&strip_offset)) { + if (err) { + (*err) += "Failed to read StripOffset value."; + } + return false; + } + + TINY_DNG_DPRINTF("strip_offset[%d] = %u\n", k, strip_offset); + image.strip_offsets.push_back(strip_offset); + } + } + + if (!sr.seek_set(uint64_t(curr_offt))) { + if (err) { + (*err) = "Failed to seek.\n"; + } + return false; + } + } + // + + // Add to images. + if (images->size() < kMaxImages) { + images->push_back(image); + } else { + if (warn) { + (*warn) = "Too many images in one DNG file. Skipped some images\n"; + } + } + + // TINY_DNG_DPRINTF("DONE ---------\n"); + + return true; +} + +static bool ParseDNGFromMemory(const StreamReader& sr, + const std::vector<FieldInfo>& custom_fields, + std::vector<tinydng::DNGImage>* images, + std::string* warn, std::string* err) { + if (!images) { + if (err) { + (*err) += "Invalid `images` argument.\n"; + } + return false; + } + + unsigned int offt; + if (!sr.read4(&offt)) { + if (err) { + (*err) += "Failed to read offset.\n"; + } + return false; + } + + TINY_DNG_DPRINTF("First IFD offt: %d\n", offt); + + size_t count = 0; + + while (offt) { + if (!sr.seek_set(offt)) { + if (err) { + (*err) += "Failed to seek to TIFF IFD.\n"; + } + return false; + } + + // TINY_DNG_DPRINTF("Parse TIFF IFD\n"); + if (!ParseTIFFIFD(sr, custom_fields, images, warn, err)) { + break; + } + // Get next IFD offset(0 = end of file). + if (!sr.read4(&offt)) { + if (err) { + (*err) += "Failed to read next IDF offset.\n"; + } + return false; + } + + TINY_DNG_DPRINTF("Next IFD offset = %d\n", offt); + + // Avoid infinite loop + count++; + if (count > kMaxImages) { + if (warn) { + (*warn) += "Too many IFDs. IFD offset seems invalid.\n"; + } + break; + } + } + + return true; +} + +static bool IsBigEndian() { + uint32_t i = 0x01020304; + char c[4]; + memcpy(c, &i, 4); + return (c[0] == 1); +} + +// C++03 and tiff lzw port of https://github.com/glampert/compression-algorithms +// ============================================================================= +// +// File: lzw.hpp +// Author: Guilherme R. Lampert +// Created on: 17/02/16 +// Brief: LZW encoder/decoder in C++11 with varying length dictionary codes. +// +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif +namespace lzw { + +class Dictionary { + public: + struct Entry { + int code; + int value; + }; + + // Dictionary entries 0-255 are always reserved to the byte/ASCII range. + int size_; + Entry entries_[4096]; + + Dictionary(); + int findIndex(int code, int value) const; + bool add(int code, int value); + bool flush(int& codeBitsWidth); + void init(); + int size() { return size_; } +}; + +// ======================================================== +// class Dictionary: +// ======================================================== + +Dictionary::Dictionary() { init(); } + +void Dictionary::init() { + // First 256 dictionary entries are reserved to the byte/ASCII + // range. Additional entries follow for the character sequences + // found in the input. Up to 4096 - 256 (MaxDictEntries - FirstCode). + size_ = 256; + for (int i = 0; i < size_; ++i) { + entries_[i].code = -1; + entries_[i].value = i; + } + + // 256 is reserved for ClearCode, 257 is reserved for end of stream, thus + // FistCode starts with 258 + size_ = 258; // = 256 + 2 +} + +int Dictionary::findIndex(const int code, const int value) const { + if (code == -1) { + return value; + } + + // Linear search for now. + // TODO: Worth optimizing with a proper hash-table? + for (int i = 0; i < size_; ++i) { + if (entries_[i].code == code && entries_[i].value == value) { + return i; + } + } + + return -1; +} + +bool Dictionary::add(const int code, const int value) { + //TINY_DNG_ASSERT(code <= size_, + // "`code' must be less than or equal to dictionary size."); + TINY_DNG_CHECK_AND_RETURN_C(code <= size_, false); + if (size_ == 4096) { + TINY_DNG_DPRINTF("Dictionary overflowed!"); + return false; + } + + TINY_DNG_DPRINTF("add[%d].code = %d\n", size_, code); + TINY_DNG_DPRINTF("add[%d].value = %d\n", size_, value); + entries_[size_].code = code; + entries_[size_].value = value; + ++size_; + return true; +} + +bool Dictionary::flush(int& codeBitsWidth) { + if (size_ == ((1 << codeBitsWidth) - 1)) { + ++codeBitsWidth; + TINY_DNG_DPRINTF("expand: bits %d\n", codeBitsWidth); + if (codeBitsWidth > 12) // MaxDictBits + { + // Clear the dictionary (except the first 256 byte entries). + codeBitsWidth = 9; // StartBits + size_ = 256 + 2; // 256 is reserved for ClearCode, 257 is reserved for + // end of stream, thus FistCode starts with 258 + return true; + } + } + return false; +} + +class BitStreamReader { + public: + // No copy/assignment. + // BitStreamReader(const BitStreamReader &) = delete; + // BitStreamReader & operator = (const BitStreamReader &) = delete; + + // BitStreamReader(const BitStreamWriter & bitStreamWriter); + BitStreamReader(const uint8_t* bitStream, int byteCount, int bitCount); + + bool isEndOfStream() const; + bool readNextBitLE(int& bitOut); // little endian + bool readNextBitBE(int& bitOut); // big endian + uint64_t readBitsU64LE(int bitCount); // little endian + uint64_t readBitsU64BE(int bitCount); // big endian + void reset(); + + private: + const uint8_t* + stream; // Pointer to the external bit stream. Not owned by the reader. + const int + sizeInBytes; // Size of the stream *in bytes*. Might include padding. + const int sizeInBits; // Size of the stream *in bits*, padding *not* include. + int currBytePos; // Current byte being read in the stream. + int nextBitPos; // Bit position within the current byte to access next. 0 to + // 7. + int numBitsRead; // Total bits read from the stream so far. Never includes + // byte-rounding padding. +}; + +// BitStreamReader::BitStreamReader(const BitStreamWriter & bitStreamWriter) +// : stream(bitStreamWriter.getBitStream()) +// , sizeInBytes(bitStreamWriter.getByteCount()) +// , sizeInBits(bitStreamWriter.getBitCount()) +//{ +// reset(); +//} + +BitStreamReader::BitStreamReader(const unsigned char* bitStream, + const int byteCount, const int bitCount) + : stream(bitStream), sizeInBytes(byteCount), sizeInBits(bitCount) { + (void)sizeInBytes; + reset(); +} + +bool BitStreamReader::readNextBitLE(int& bitOut) { + if (numBitsRead >= sizeInBits) { + return false; // We are done. + } + + const uint32_t mask = uint32_t(1) << nextBitPos; + bitOut = !!(stream[currBytePos] & mask); + ++numBitsRead; + + if (++nextBitPos == 8) { + nextBitPos = 0; + ++currBytePos; + } + return true; +} + +bool BitStreamReader::readNextBitBE(int& bitOut) { + if (numBitsRead >= sizeInBits) { + return false; // We are done. + } + + const uint32_t mask = uint32_t(1) << (7 - nextBitPos); + bitOut = !!(stream[currBytePos] & mask); + ++numBitsRead; + + if (++nextBitPos == 8) { + nextBitPos = 0; + ++currBytePos; + } + return true; +} + +uint64_t BitStreamReader::readBitsU64LE(const int bitCount) { + //TINY_DNG_ASSERT(bitCount <= 64, + // "`bitCount' must be less than or equal to 64."); + TINY_DNG_CHECK_AND_RETURN_C(bitCount <= 64, 0); + + uint64_t num = 0; + for (int b = 0; b < bitCount; ++b) { + int bit; + if (!readNextBitLE(bit)) { + TINY_DNG_DPRINTF( + "LE: Failed to read bits from stream! Unexpected end.\n"); + break; + } + + // Based on a "Stanford bit-hack": + // http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching + const uint64_t mask = uint64_t(1) << b; + num = (num & ~mask) | (uint64_t(-bit) & mask); + } + + return num; +} + +uint64_t BitStreamReader::readBitsU64BE(const int bitCount) { + //TINY_DNG_ASSERT(bitCount <= 64, + // "`bitCount' must be less than or equal to 64."); + TINY_DNG_CHECK_AND_RETURN_C(bitCount <= 64, 0); + + uint64_t num = 0; + for (int b = 0; b < bitCount; ++b) { + int bit; + if (!readNextBitBE(bit)) { + TINY_DNG_DPRINTF("BE: Failed to read bits from stream! Unexpected end."); + break; + } + + TINY_DNG_DPRINTF("bit[%d](count %d) = %d\n", b, bitCount, bit); + + // Based on a "Stanford bit-hack": + // http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching + const uint64_t mask = uint64_t(1) << (bitCount - b - 1); + num = (num & ~mask) | (uint64_t(-bit) & mask); + } + + TINY_DNG_DPRINTF("num = %d\n", int(num)); + return num; +} + +void BitStreamReader::reset() { + currBytePos = 0; + nextBitPos = 0; + numBitsRead = 0; +} + +bool BitStreamReader::isEndOfStream() const { + return numBitsRead >= sizeInBits; +} + +// ======================================================== +// easyDecode() and helpers: +// ======================================================== + +static bool outputByte(int code, unsigned char*& output, int outputSizeBytes, + int& bytesDecodedSoFar) { + if (bytesDecodedSoFar >= outputSizeBytes) { + // LZW_ERROR("Decoder output buffer too small!"); + return false; + } + + //TINY_DNG_ASSERT(code >= 0 && code < 256, "`code' must be within [0, 255]."); + TINY_DNG_CHECK_AND_RETURN_C(code >= 0 && code < 256, false); + *output++ = static_cast<unsigned char>(code); + ++bytesDecodedSoFar; + return true; +} + +static bool outputSequence(const Dictionary& dict, int code, + unsigned char*& output, int outputSizeBytes, + int& bytesDecodedSoFar, int& firstByte) { + const int MaxDictEntries = 4096; + (void)MaxDictEntries; + + // A sequence is stored backwards, so we have to write + // it to a temp then output the buffer in reverse. + int i = 0; + unsigned char sequence[4096]; + do { + //TINY_DNG_ASSERT(i < MaxDictEntries - 1 && code >= 0, + // "Invalid value for `i' or `code'."); + TINY_DNG_CHECK_AND_RETURN_C(i < MaxDictEntries - 1 && code >= 0, false); + TINY_DNG_DPRINTF("i = %d, ent[%d].value = %d\n", i, code, + dict.entries_[code].value); + sequence[i++] = static_cast<unsigned char>(dict.entries_[code].value); + code = dict.entries_[code].code; + } while (code >= 0); + + firstByte = sequence[--i]; + for (; i >= 0; --i) { + if (!outputByte(sequence[i], output, outputSizeBytes, bytesDecodedSoFar)) { + return false; + } + } + return true; +} + +static int easyDecode(const unsigned char* compressed, + const int compressedSizeBytes, + const int compressedSizeBits, unsigned char* uncompressed, + const int uncompressedSizeBytes, const bool swap_endian) { + const int Nil = -1; + const int MaxDictBits = 12; + const int StartBits = 9; + + // TIFF specific values + const int ClearCode = 256; + const int EndOfInformation = 257; + + if (compressed == NULL || uncompressed == NULL) { + TINY_DNG_DPRINTF("lzw::easyDecode(): Null data pointer(s)!\n"); + return 0; + } + + if (compressedSizeBytes <= 0 || compressedSizeBits <= 0 || + uncompressedSizeBytes <= 0) { + TINY_DNG_DPRINTF("lzw::easyDecode(): Bad in/out sizes!n"); + return 0; + } + + int code = Nil; + int prevCode = Nil; + int firstByte = 0; + int bytesDecoded = 0; + int codeBitsWidth = StartBits; + + // We'll reconstruct the dictionary based on the + // bit stream codes. Unlike Huffman encoding, we + // don't store the dictionary as a prefix to the data. + Dictionary dictionary; + BitStreamReader bitStream(compressed, compressedSizeBytes, + compressedSizeBits); + + // We check to avoid an overflow of the user buffer. + // If the buffer is smaller than the decompressed size, + // TINY_DNG_DPRINTF() is called. If that doesn't throw or + // terminate we break the loop and return the current + // decompression count. + while (!bitStream.isEndOfStream()) { + //TINY_DNG_ASSERT( + // codeBitsWidth <= MaxDictBits, + // "`codeBitsWidth must be less than or equal to `MaxDictBits'."); + TINY_DNG_CHECK_AND_RETURN_C(codeBitsWidth <= MaxDictBits, 0); + (void)MaxDictBits; + + if (!swap_endian) { // TODO(syoyo): Detect BE or LE depending on endianness + // in stored format and host endian + code = static_cast<int>(bitStream.readBitsU64BE(codeBitsWidth)); + } else { + code = static_cast<int>(bitStream.readBitsU64LE(codeBitsWidth)); + } + + TINY_DNG_DPRINTF("code = %d(swap_endian = %d)\n", code, swap_endian); + + // if (code >= dictionary.size()) { + // std::cerr << "code = " << code << "dict.size = " << dictionary.size() << + // std::endl; + //} + + // TINY_DNG_ASSERT(code <= dictionary.size(), + // "`code' must be less than or equal to dictionary size."); + + if (code == EndOfInformation) { + TINY_DNG_DPRINTF("EoI\n"); + break; + } + + if (code == ClearCode) { + // Initialize dict. + dictionary.init(); + codeBitsWidth = StartBits; + + if (!swap_endian) { + code = static_cast<int>(bitStream.readBitsU64BE(codeBitsWidth)); + } else { + code = static_cast<int>(bitStream.readBitsU64LE(codeBitsWidth)); + } + + if (code == EndOfInformation) { + TINY_DNG_DPRINTF("EoI\n"); + break; + } + + if (!outputByte(code, uncompressed, uncompressedSizeBytes, + bytesDecoded)) { + break; + } + + prevCode = code; + continue; + } + + if (prevCode == Nil) { + if (!outputByte(code, uncompressed, uncompressedSizeBytes, + bytesDecoded)) { + break; + } + firstByte = code; + prevCode = code; + continue; + } + + if (code >= dictionary.size()) { + if (!outputSequence(dictionary, prevCode, uncompressed, + uncompressedSizeBytes, bytesDecoded, firstByte)) { + break; + } + if (!outputByte(firstByte, uncompressed, uncompressedSizeBytes, + bytesDecoded)) { + break; + } + } else { + if (!outputSequence(dictionary, code, uncompressed, uncompressedSizeBytes, + bytesDecoded, firstByte)) { + break; + } + } + + dictionary.add(prevCode, firstByte); + if (dictionary.flush(codeBitsWidth)) { + TINY_DNG_DPRINTF("flush\n"); + prevCode = Nil; + } else { + prevCode = code; + } + } + + return bytesDecoded; +} + +// ============================================================================= +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +} // namespace lzw + +#if defined(_WIN32) +namespace { + +static inline std::wstring UTF8ToWchar(const std::string& str) { + int wstr_size = + MultiByteToWideChar(CP_UTF8, 0, str.data(), int(str.size()), NULL, 0); + if (wstr_size < 0) { + // ??? wstr_size must be positive + return std::wstring(); + } + std::wstring wstr(size_t(wstr_size), 0); + MultiByteToWideChar(CP_UTF8, 0, str.data(), int(str.size()), &wstr[0], + int(wstr.size())); + return wstr; +} + +} // namespace +#endif + +bool LoadDNG(const char* filename, std::vector<FieldInfo>& custom_fields, + std::vector<DNGImage>* images, std::string* warn, + std::string* err) { + (void)warn; + std::stringstream ss; + + if (!images) { + if (err) { + (*err) += "Invalid `images` pointer.\n"; + } + return false; + } + + FILE* fp; +#if defined(_WIN32) + +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = _wfopen_s(&fp, UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + if (err) { + (*err) += "Error opening file: " + std::string(filename) + "(errno " + + std::to_string(errcode) + ")\n"; + } + return false; + } +#else + // Unknown compiler + fp = fopen(filename, "rb"); +#endif + +#else + fp = fopen(filename, "rb"); +#endif + + if (!fp) { + ss << "File not found or cannot open file " << filename << std::endl; + if (err) { + (*err) = ss.str(); + } + return false; + } + + if (0 != fseek(fp, 0, SEEK_END)) { + if (err) { + (*err) = "Error seeking.\n"; + } + return false; + } + + size_t file_size = static_cast<size_t>(ftell(fp)); + + std::vector<unsigned char> whole_data; + { + whole_data.resize(file_size); + fseek(fp, 0, SEEK_SET); + size_t read_len = fread(whole_data.data(), 1, file_size, fp); + if (read_len != file_size) { + if (err) { + (*err) += "Unexpected file size.\n"; + } + return false; + } + + fseek(fp, 0, SEEK_SET); + } + fclose(fp); + + return LoadDNGFromMemory(reinterpret_cast<const char*>(whole_data.data()), + static_cast<unsigned int>(whole_data.size()), + custom_fields, images, warn, err); +} + +bool LoadDNGFromMemory(const char* mem, unsigned int size, + std::vector<FieldInfo>& custom_fields, + std::vector<DNGImage>* images, std::string* warn, + std::string* err) { + (void)warn; + + if ((mem == NULL) || (size < 32) || (!images)) { + if (err) { + (*err) = "Invalid argument. argument is null or invalid.\n"; + } + return false; + } + + bool is_dng_big_endian = false; + + const unsigned short magic = *(reinterpret_cast<const unsigned short*>(mem)); + + if (magic == 0x4949) { + // might be TIFF(DNG). + } else if (magic == 0x4d4d) { + // might be TIFF(DNG, bigendian). + is_dng_big_endian = true; + TINY_DNG_DPRINTF("DNG is big endian\n"); + } else { + std::stringstream ss; + ss << "Seems the data is not a DNG format." << std::endl; + if (err) { + (*err) = ss.str(); + } + + return false; + } + + const bool swap_endian = (is_dng_big_endian && (!IsBigEndian())); + StreamReader sr(reinterpret_cast<const uint8_t*>(mem), size, swap_endian); + + char header[32]; + + if (32 != sr.read(32, 32, reinterpret_cast<unsigned char*>(header))) { + if (err) { + (*err) = "Error reading header.\n"; + } + return false; + } + + // skip magic header + if (!sr.seek_set(4)) { + if (err) { + (*err) += "Failed to seek to offset 4.\n"; + } + return false; + } + + bool ret = ParseDNGFromMemory(sr, custom_fields, images, warn, err); + + if (!ret) { + if (err) { + (*err) += "Failed to parse DNG data.\n"; + } + return false; + } + + // + // Decode image data. + // + for (size_t i = 0; i < images->size(); i++) { + tinydng::DNGImage* image = &((*images)[i]); + + const size_t data_offset = + (image->offset > 0) ? image->offset : image->tile_offset; + TINY_DNG_DPRINTF("data_offset = %d\n", int(data_offset)); + if ((data_offset == 0) || (data_offset > sr.size())) { + if (err) { + std::stringstream ss; + ss << i << "'th image data offset is zero or invalid.\n"; + (*err) += ss.str(); + } + return false; + } + + // std::cout << "offt =\n" << image->offset << std::endl; + // std::cout << "tile_offt = \n" << image->tile_offset << std::endl; + // std::cout << "data_offset = " << data_offset << std::endl; + + TINY_DNG_DPRINTF("image[%d].compression = %d\n", int(i), + image->compression); + + if (image->compression == COMPRESSION_NONE) { // no compression + + if (image->jpeg_byte_count > 0) { + // Looks like CR2 IFD#1(thumbnail jpeg image) + // Currently skip parsing jpeg data. + // TODO(syoyo): Decode jpeg data. + image->width = 0; + image->height = 0; + + if (image->bits_per_sample_original < 0) { + // Assume 8bit + image->bits_per_sample_original = 8; + } + + image->bits_per_sample = image->bits_per_sample_original; + + } else { + + const size_t kMaxImageSize = size_t(1024)*size_t(1024)*size_t(1024)*size_t(2); // 2GB + + if (image->bits_per_sample_original <= 0) { + if (err) { + (*err) += "bits_per_sample information not found in the tag.\n"; + } + return false; + } + + image->bits_per_sample = image->bits_per_sample_original; + // std::cout << "sample_per_pixel " << image->samples_per_pixel << "\n"; + // std::cout << "width " << image->width << "\n"; + // std::cout << "height " << image->height << "\n"; + // std::cout << "bps " << image->bits_per_sample << "\n"; + + if (((image->width * image->height * image->bits_per_sample) % 8) == + 0) { + // OK + } else { + if (err) { + (*err) += "Image size must be multiple of 8."; + } + return false; + } + + const size_t len = size_t(image->samples_per_pixel) * + size_t(image->width) * size_t(image->height) * + size_t(image->bits_per_sample) / size_t(8); + + if (len == 0) { + if (err) { + (*err) += "Unexpected length."; + } + return false; + } + + if (len > kMaxImageSize) { + if (err) { + std::stringstream ss; + ss << "Image byte size too large. " << len << "bytes in file, but hard-limit is set to " << kMaxImageSize << " bytes.\n"; + (*err) += ss.str(); + } + return false; + } + + image->data.resize(len); + if (!sr.seek_set(data_offset)) { + if (err) { + (*err) += "Failed to seek to uncompressed image data position.\n"; + } + return false; + } + + if (!sr.read(len, len, image->data.data())) { + if (err) { + (*err) += "Failed to read image data.\n"; + } + return false; + } + } + } else if (image->compression == COMPRESSION_LZW) { // lzw compression + + if (image->bits_per_sample_original <= 0) { + if (err) { + (*err) += "bits_per_sample information not found in the tag.\n"; + } + return false; + } + + image->bits_per_sample = image->bits_per_sample_original; + TINY_DNG_DPRINTF("bps = %d\n", image->bits_per_sample); + TINY_DNG_DPRINTF("counts = %d\n", int(image->strip_byte_counts.size())); + TINY_DNG_DPRINTF("offsets = %d\n", int(image->strip_offsets.size())); + + image->data.clear(); + + if ((image->strip_byte_counts.size() > 0) && + (image->strip_byte_counts.size() == image->strip_offsets.size())) { +#if (__cplusplus > 199711L) && defined(TINY_DNG_LOADER_USE_THREAD) + + const int num_strips = int(image->strip_byte_counts.size()); + + std::vector<std::thread> workers; + std::atomic<size_t> strip_count(0); + std::mutex err_mtx_; + + int num_threads = (std::max)(1, int(std::thread::hardware_concurrency())); + if (num_threads > num_strips) { + num_threads = num_strips; + } + + bool failed = false; + + const size_t dst_strip_len = static_cast<size_t>( + (image->samples_per_pixel * image->width * image->rows_per_strip * + image->bits_per_sample) / + 8); + + image->data.resize(dst_strip_len * size_t(num_strips)); + + for (int t = 0; t < num_threads; t++) { + workers.emplace_back(std::thread([&]() { + size_t k = 0; + while ((k = strip_count++) < size_t(num_strips)) { + std::vector<unsigned char> src(image->strip_byte_counts[k]); + size_t strip_offset = image->strip_offsets[k]; + size_t strip_bytesize = image->strip_byte_counts[k]; + + std::vector<unsigned char> dst(dst_strip_len); + + const uint8_t* src_addr = + sr.map_abs_addr(strip_offset, strip_bytesize); + + if (!src_addr) { + // Atomic update + { + std::lock_guard<std::mutex> lock(err_mtx_); + if (err) { + (*err) += + "Cannot read strip_byte_counts bytes from a memory.\n"; + } + } + + failed = true; + break; + } + + TINY_DNG_DPRINTF("easyDecode begin\n"); + int decoded_bytes = lzw::easyDecode( + src_addr, int(strip_bytesize), + int(strip_bytesize) * + image + ->bits_per_sample /* FIXME(syoyo): Is this correct? */ + , + dst.data(), int(dst_strip_len), swap_endian); + TINY_DNG_DPRINTF("easyDecode done\n"); + if (decoded_bytes <= 0) { + { + std::lock_guard<std::mutex> lock(err_mtx_); + if (err) { + (*err) += + "lzw decode failed.\n"; + } + } + + failed = true; + break; + } + + if (image->predictor == 1) { + // no prediction shceme + } else if (image->predictor == 2) { + // horizontal diff + + const size_t stride = + size_t(image->width * image->samples_per_pixel); + const size_t spp = size_t(image->samples_per_pixel); + for (size_t row = 0; row < size_t(image->rows_per_strip); + row++) { + for (size_t c = 0; c < size_t(image->samples_per_pixel); + c++) { + unsigned int b = dst[row * stride + c]; + for (size_t col = 1; col < size_t(image->width); col++) { + // value may overflow(wrap over), but its expected + // behavior. + b += dst[stride * row + spp * col + c]; + dst[stride * row + spp * col + c] = + static_cast<unsigned char>(b & 0xFF); + } + } + } + + } else if (image->predictor == 3) { + // fp horizontal diff. + //TINY_DNG_ABORT("[TODO] FP horizontal differencing predictor."); + { + std::lock_guard<std::mutex> lock(err_mtx_); + if (err) { + (*err) += + "[TODO] FP horizontal differencing predictor(3)\n"; + } + } + failed = true; + break; + } else { + //TINY_DNG_ABORT("Invalid predictor value."); + { + std::lock_guard<std::mutex> lock(err_mtx_); + if (err) { + (*err) += + "Invalid predictor value.\n"; + } + } + failed = true; + break; + } + + memcpy(&image->data[k * dst_strip_len], dst.data(), + dst_strip_len); + } + })); + } + + for (auto& t : workers) { + t.join(); + } + + // something failed in a thread. + if (failed) { + return false; + } + +#else + for (size_t k = 0; k < image->strip_byte_counts.size(); k++) { + std::vector<unsigned char> src(image->strip_byte_counts[k]); + if (!sr.seek_set(image->strip_offsets[k])) { + if (err) { + (*err) += "Failed to seek to strip offset.\n"; + } + return false; + } + + const uint64_t dst_len = uint64_t(image->samples_per_pixel) * uint64_t(image->width) * uint64_t(image->rows_per_strip) * + uint64_t(image->bits_per_sample) / 8ull; + if (dst_len == 0) { + if (err) { + (*err) += "Image data size is zero. Something is wrong in Image parameter:\n"; + (*err) += " samples_per_pixel " + std::to_string(image->samples_per_pixel) + "\n"; + (*err) += " width " + std::to_string(image->width) + "\n"; + (*err) += " rows_per_strip " + std::to_string(image->rows_per_strip) + "\n"; + (*err) += " bits_per_sample " + std::to_string(image->bits_per_sample) + "\n"; + } + return false; + } + + if (dst_len > (kMaxImageSizeInMB * 1024ull * 1024ull)) { + if (err) { + (*err) += "Image data size too large. Exceeds " + std::to_string(kMaxImageSizeInMB) + " MB.\n"; + } + return false; + } + std::vector<unsigned char> dst(dst_len); + + if (!sr.read(image->strip_byte_counts[k], image->strip_byte_counts[k], + src.data())) { + if (err) { + (*err) += "Cannot read strip_byte_counts bytes from stream.\n"; + } + return false; + } + TINY_DNG_DPRINTF("easyDecode begin\n"); + int decoded_bytes = lzw::easyDecode( + src.data(), int(image->strip_byte_counts[k]), + int(image->strip_byte_counts[k]) * + image->bits_per_sample /* FIXME(syoyo): Is this correct? */, + dst.data(), int(dst_len), swap_endian); + TINY_DNG_DPRINTF("easyDecode done\n"); + if (decoded_bytes <= 0) { + TINY_DNG_ERROR_AND_RETURN("decoded_ bytes must be non-zero positive.", err); + } + + if (image->predictor == 1) { + // no prediction shceme + } else if (image->predictor == 2) { + // horizontal diff + + const size_t stride = + size_t(image->width * image->samples_per_pixel); + const size_t spp = size_t(image->samples_per_pixel); + for (size_t row = 0; row < size_t(image->rows_per_strip); row++) { + for (size_t c = 0; c < size_t(image->samples_per_pixel); c++) { + unsigned int b = dst[row * stride + c]; + for (size_t col = 1; col < size_t(image->width); col++) { + // value may overflow(wrap over), but its expected behavior. + b += dst[stride * row + spp * col + c]; + dst[stride * row + spp * col + c] = + static_cast<unsigned char>(b & 0xFF); + } + } + } + + } else if (image->predictor == 3) { + // fp horizontal diff. + TINY_DNG_ERROR_AND_RETURN("[TODO} FP horizontal differencing predictor(3).", err); + } else { + TINY_DNG_ERROR_AND_RETURN("Invalid predictor value.", err); + } + + std::copy(dst.begin(), dst.end(), std::back_inserter(image->data)); + } + +#endif + } else { + TINY_DNG_ERROR_AND_RETURN("Unsupported image strip configuration.", err); + } + } else if (image->compression == + COMPRESSION_OLD_JPEG) { // old jpeg compression + + // std::cout << "IFD " << i << std::endl; + + // First check if JPEG is lossless JPEG + // TODO(syoyo): Compure conservative data_len. + if (sr.size() < data_offset) { + if (err) { + (*err) += "Unexpected data offset.\n"; + } + return false; + } + size_t data_len = sr.size() - data_offset; + int lj_width = -1, lj_height = -1, lj_bits = -1, lj_components = -1; + if (IsLosslessJPEG(sr.data() + data_offset, static_cast<int>(data_len), + &lj_width, &lj_height, &lj_bits, &lj_components)) { + // std::cout << "IFD " << i << " is LJPEG" << std::endl; + TINY_DNG_DPRINTF("IFD[%d] is LJPEG\n", int(i)); + + TINY_DNG_CHECK_AND_RETURN( + lj_width > 0 && lj_height > 0 && lj_bits > 0 && lj_components > 0, + "Image dimensions must be > 0.", err); + + // Assume not in tiled format. + TINY_DNG_CHECK_AND_RETURN(image->tile_width == -1 && image->tile_length == -1, + "Tiled format not supported tile size.", err); + + image->height = lj_height; + + // Is Canon CR2? + const bool is_cr2 = (image->cr2_slices[0] != 0) ? true : false; + + if (is_cr2) { + // For CR2 RAW, slices[0] * slices[1] + slices[2] = image width + image->width = image->cr2_slices[0] * image->cr2_slices[1] + + image->cr2_slices[2]; + } else { + image->width = lj_width; + } + + image->bits_per_sample_original = lj_bits; + + // lj92 decodes data into 16bits, so modify bps. + image->bits_per_sample = 16; + + TINY_DNG_CHECK_AND_RETURN( + ((image->width * image->height * image->bits_per_sample) % 8) == 0, + "Image size must be multiple of 8.", err); + const size_t len = + static_cast<size_t>((image->samples_per_pixel * image->width * + image->height * image->bits_per_sample) / + 8); + // std::cout << "spp = " << image->samples_per_pixel; + // std::cout << ", w = " << image->width << ", h = " << image->height << + // ", bps = " << image->bits_per_sample << std::endl; + TINY_DNG_CHECK_AND_RETURN(len > 0, "Invalid length.", err); + image->data.resize(len); + + if (sr.size() < data_offset) { + if (err) { + (*err) += "Unexpected file size or data offset.\n"; + } + return false; + } + + std::vector<unsigned short> buf; + buf.resize(static_cast<size_t>(image->width * image->height * + image->samples_per_pixel)); + + bool ok = DecompressLosslessJPEG(sr, &buf.at(0), image->width, (*image), + NULL, err); + if (!ok) { + if (err) { + std::stringstream ss; + ss << "Failed to decompress LJPEG." << std::endl; + (*err) = ss.str(); + } + return false; + } + + if (is_cr2) { + // CR2 stores image in tiled format(image slices. left to right). + // Convert it to scanline format. + int nslices = image->cr2_slices[0]; + int slice_width = image->cr2_slices[1]; + int slice_remainder_width = image->cr2_slices[2]; + size_t src_offset = 0; + + unsigned short* dst_ptr = + reinterpret_cast<unsigned short*>(image->data.data()); + + for (int slice = 0; slice < nslices; slice++) { + int x_offset = slice * slice_width; + for (int y = 0; y < image->height; y++) { + size_t dst_offset = + static_cast<size_t>(y * image->width + x_offset); + memcpy(&dst_ptr[dst_offset], &buf[src_offset], + sizeof(unsigned short) * static_cast<size_t>(slice_width)); + src_offset += static_cast<size_t>(slice_width); + } + } + + // remainder(the last slice). + { + int x_offset = nslices * slice_width; + for (int y = 0; y < image->height; y++) { + size_t dst_offset = + static_cast<size_t>(y * image->width + x_offset); + // std::cout << "y = " << y << ", dst = " << dst_offset << ", src + // = " << src_offset << ", len = " << buf.size() << std::endl; + memcpy(&dst_ptr[dst_offset], &buf[src_offset], + sizeof(unsigned short) * + static_cast<size_t>(slice_remainder_width)); + src_offset += static_cast<size_t>(slice_remainder_width); + } + } + + } else { + memcpy(image->data.data(), static_cast<void*>(&(buf.at(0))), len); + } + + } else { + // Baseline 8bit JPEG + + image->bits_per_sample_original = 8; + image->bits_per_sample = 8; + + size_t jpeg_len = static_cast<size_t>(image->jpeg_byte_count); + if (image->jpeg_byte_count == -1) { + // No jpeg datalen. Set to the size of file - offset. + if (sr.size() < data_offset) { + if (err) { + (*err) += "Unexpected file size or data offset.\n"; + } + return false; + } + jpeg_len = sr.size() - data_offset; + } + + if (jpeg_len == 0) { + if (err) { + (*err) += "Invalid jpeg data length.\n"; + } + return false; + } + + // Assume RGB jpeg + // + // First check the header. + int w_info = 0, h_info = 0, components_info = 0; + int is_jpeg = stbi_info_from_memory(sr.data() + data_offset, + static_cast<int>(jpeg_len), &w_info, + &h_info, &components_info); + if (is_jpeg != 1) { + if (err) { + (*err) += "Not a JPEG data.\n"; + } + return false; + } + + if ((components_info != 1) && (components_info != 3)) { + if (err) { + (*err) += "Unsupported channels in JPEG data.\n"; + } + return false; + } + + if ((w_info < 1) || (h_info < 1)) { + if (err) { + (*err) += "Invalid JPEG image resolution.\n"; + } + return false; + } + + int w = 0, h = 0, components = 0; + + // Check if data is in valid range. + if ((sr.tell() + data_offset + static_cast<uint32_t>(jpeg_len)) >= sr.size()) { + if (err) { + (*err) += "Invalid JPEG image data size.\n"; + } + return false; + } + + unsigned char* decoded_image = stbi_load_from_memory( + sr.data() + data_offset, static_cast<uint32_t>(jpeg_len), &w, &h, + &components, /* desired_channels */ components_info); + TINY_DNG_CHECK_AND_RETURN(decoded_image, "Could not decode JPEG image.", err); + + // Currently we just discard JPEG image(since JPEG image would be just a + // thumbnail or LDR image of RAW). + // TODO(syoyo): Do not discard JPEG image. + free(decoded_image); + + // std::cout << "w = " << w << std::endl; + // std::cout << "h = " << w << std::endl; + // std::cout << "c = " << components << std::endl; + + TINY_DNG_CHECK_AND_RETURN(w > 0 && h > 0, "Image dimensions must be > 0.", err); + + image->width = w; + image->height = h; + } + + } else if (image->compression == + COMPRESSION_NEW_JPEG) { // new JPEG(baseline DCT JPEG or + // lossless JPEG) + + bool decoded = false; + + if (image->bits_per_sample_original == 8) { + // bps TAG exists. probably ordinal JPEG + + size_t jpeg_len = static_cast<size_t>(image->jpeg_byte_count); + if (image->jpeg_byte_count == -1) { + // No jpeg datalen. Set to the size of file - offset. + if (sr.size() < data_offset) { + if (err) { + (*err) += "Unexpected file size or data offset.\n"; + } + return false; + } + jpeg_len = sr.size() - data_offset; + } + + int w_info = 0, h_info = 0, components_info = 0; + int is_jpeg = stbi_info_from_memory(sr.data() + data_offset, + static_cast<int>(jpeg_len), &w_info, + &h_info, &components_info); + + if (is_jpeg != 1) { + // Try to decode image as lossless JPEG. + } else { + int w = 0, h = 0, components = 0; + unsigned char* decoded_image = stbi_load_from_memory( + sr.data() + data_offset, static_cast<int>(jpeg_len), &w, &h, + &components, /* desired_channels */ components_info); + + if (!decoded_image) { + // Try to decode image as lossless JPEG. + } else { + decoded = true; + + image->width = w; + image->height = h; + image->samples_per_pixel = components; + image->bits_per_sample = image->bits_per_sample_original; + + const uint64_t len = uint64_t(image->samples_per_pixel) * uint64_t(image->width) * uint64_t(image->height) * uint64_t(image->bits_per_sample / 8); + // For 32bit + if (sizeof(void *) == 4) { + // Use 2GB as a max + if (len > uint64_t((std::numeric_limits<int32_t>::max)())) { + if (err) { + (*err) += "Decoded image size exceeds 2GB.\n"; + } + return false; + } + } + + if (len > (kMaxImageSizeInMB * 1024ull * 1024ull)) { + if (err) { + (*err) += "Image data size too large. Exceeds " + std::to_string(kMaxImageSizeInMB) + " MB.\n"; + } + return false; + } + + if (len == 0) { + if (err) { + std::stringstream ss; + ss << "Image size is 0. Something is wrong in Image parameter:\n"; + ss << " width = " << image->width << "\n"; + ss << " height = " << image->height << "\n"; + ss << " spp = " << image->samples_per_pixel << "\n"; + ss << " bps = " << image->bits_per_sample << "\n"; + + (*err) += ss.str(); + } + return false; + } + + image->data.resize(len); + + memcpy(image->data.data(), decoded_image, len); + + free(decoded_image); + } + } + } + + if (!decoded) { + // Try to decode as lossless JPEG. + + // lj92 decodes data into 16bits, so modify bps. + image->bits_per_sample = 16; + + // std::cout << "w = " << image->width << ", h = " << image->height << + // std::endl; + + TINY_DNG_DPRINTF("image.width = %d\n", image->width); + TINY_DNG_DPRINTF("image.height = %d\n", image->height); + TINY_DNG_DPRINTF("image.bps = %d\n", image->bits_per_sample); + TINY_DNG_DPRINTF("image.spp = %d\n", image->samples_per_pixel); + + TINY_DNG_CHECK_AND_RETURN( + ((image->width * image->height * image->bits_per_sample) % 8) == 0, + "Image must be multiple of 8.", err); + const uint64_t len = uint64_t(image->samples_per_pixel) * uint64_t(image->width) * uint64_t(image->height) * uint64_t(image->bits_per_sample / 8); + // For 32bit + if (sizeof(void *) == 4) { + // Use 2GB as a max + if (len > uint64_t((std::numeric_limits<int32_t>::max)())) { + if (err) { + (*err) += "Decoded image size exceeds 2GB.\n"; + } + return false; + } + } + + if (len > (kMaxImageSizeInMB * 1024ull * 1024ull)) { + if (err) { + (*err) += "Image data size too large. Exceeds " + std::to_string(kMaxImageSizeInMB) + " MB.\n"; + } + return false; + } + + if (len == 0) { + if (err) { + (*err) += "Invalid jpeg data length.\n"; + } + return false; + } + TINY_DNG_DPRINTF("image.data.size = %lld\n", len); + + image->data.resize(len); + TINY_DNG_DPRINTF("image.data.size = %d\n", int(len)); + + if (sr.size() < data_offset) { + if (err) { + (*err) += "Unexpected file size or data offset.\n"; + } + return false; + } + + if (!sr.seek_set(data_offset)) { + if (err) { + (*err) += "Failed to seek to data offset(NewJpeg).\n"; + } + return false; + } + + int lj_bits = 0; + + bool ok = DecompressLosslessJPEG( + sr, reinterpret_cast<unsigned short*>(&(image->data.at(0))), + image->width, (*image), &lj_bits, err); + if (!ok) { + if (err) { + std::stringstream ss; + ss << "Failed to decompress LJPEG." << std::endl; + (*err) = ss.str(); + } + return false; + } + + if (image->bits_per_sample_original <= 0) { + image->bits_per_sample_original = lj_bits; + } + } + + } else if (image->compression == COMPRESSION_ZIP) { // ZIP +#ifdef TINY_DNG_LOADER_ENABLE_ZIP + TINY_DNG_CHECK_AND_RETURN(image->bits_per_sample_original > 0, + "bits_per_sample information not found in the tag.", err); + image->bits_per_sample = image->bits_per_sample_original; + TINY_DNG_DPRINTF("bps = %d\n", image->bits_per_sample); + TINY_DNG_DPRINTF("data_offset = %d\n", int(data_offset)); + + TINY_DNG_DPRINTF("width %d\n", image->width); + TINY_DNG_DPRINTF("height %d\n", image->height); + TINY_DNG_DPRINTF("samples_per_pixel %d\n", image->samples_per_pixel); + TINY_DNG_DPRINTF("bits_per_sample %d\n", image->bits_per_sample); + + const size_t len = + static_cast<size_t>((image->samples_per_pixel * image->width * + image->height * image->bits_per_sample) / + 8); + if (len == 0) { + if (err) { + (*err) += "Invalid length. in ZIP compressed data.\n"; + } + return false; + } + + image->data.resize(len); + + if (sr.size() < data_offset) { + if (err) { + (*err) += + "Unexpected file size or data offset in ZIP compressed data.\n"; + } + return false; + } + + if (!sr.seek_set(data_offset)) { + if (err) { + (*err) += "Failed to seek to data offset(ZIP).\n"; + } + return false; + } + + bool ok = DecompressZIPedTile(sr, &(image->data.at(0)), image->width, + (*image), err); + if (!ok) { + if (err) { + std::stringstream ss; + ss << "Failed to decompress ZIP." << std::endl; + (*err) += ss.str(); + } + return false; + } +#else + if (err) { + std::stringstream ss; + ss << "ZIP compression is not supported." << std::endl; + (*err) = ss.str(); + } +#endif + } else if (image->compression == COMPRESSION_LOSSY) { // lossy JPEG + + // TOOD: Check bps and photometric_interpretation. + + size_t jpeg_len = static_cast<size_t>(image->jpeg_byte_count); + if (image->jpeg_byte_count == -1) { + // No jpeg datalen. Set to the size of file - offset. + if (sr.size() < data_offset) { + if (err) { + (*err) += "Unexpected file size or data offset.\n"; + } + return false; + } + jpeg_len = sr.size() - data_offset; + } + + int w_info = 0, h_info = 0, components_info = 0; + int is_jpeg = stbi_info_from_memory(sr.data() + data_offset, + static_cast<int>(jpeg_len), &w_info, + &h_info, &components_info); + + if (is_jpeg != 1) { + if (err) { + (*err) += + "Currently We only supports Standard JPEG data for Lossy " + "compression(34892).\n"; + } + return false; + } + + if ((components_info != 1) && (components_info != 3)) { + if (err) { + (*err) += "Unsupported channels in JPEG data.\n"; + } + return false; + } + + if ((w_info < 1) || (h_info < 1)) { + if (err) { + (*err) += "Invalid JPEG image resolution.\n"; + } + return false; + } + + int w = 0, h = 0, components = 0; + unsigned char* decoded_image = stbi_load_from_memory( + sr.data() + data_offset, static_cast<int>(jpeg_len), &w, &h, + &components, /* desired_channels */ components_info); + + + if (!decoded_image) { + // Probably 16bit JPEG? + image->bits_per_sample_original = 1; // FIXME + image->bits_per_sample = 1; // FIXME + + if (err) { + std::stringstream ss; + ss << "Unsupported lossy JPEG compression(16bit JPEG?)." << std::endl; + (*err) = ss.str(); + } + + } else { + image->width = w; + image->height = h; + image->samples_per_pixel = components; + image->bits_per_sample = 8; + + const size_t len = + static_cast<size_t>((image->samples_per_pixel * image->width * + image->height * image->bits_per_sample) / + 8); + image->data.resize(len); + + memcpy(image->data.data(), decoded_image, len); + +#if defined(TINY_DNG_DEBUG_SAVEIMAGE) + std::string output_filename = "layer-" + std::to_string(i) + ".png"; + stbi_write_png(output_filename.c_str(), w, h, components, + reinterpret_cast<const void*>(decoded_image), + /* stride */ 0); +#endif + free(decoded_image); + } + + } else if (image->compression == 34713) { // NEF lossless? + + image->bits_per_sample_original = 1; // FIXME + image->bits_per_sample = 1; // FIXME + + if (err) { + std::stringstream ss; + ss << "Seems a NEF RAW. This compression is not supported." + << std::endl; + (*err) = ss.str(); + } + } else { + if (err) { + std::stringstream ss; + ss << "IFD [" << i << "] " + << " Unsupported compression type : " << image->compression + << std::endl; + (*err) = ss.str(); + } + return false; + } + } + + // + // Postprocessing. Calculate while_level. + // + for (size_t i = 0; i < images->size(); i++) { + tinydng::DNGImage* image = &((*images)[i]); + + if (image->samples_per_pixel > 4) { + if (err) { + (*err) += "Cannot handle > 4 samples per pixel.\n"; + } + return false; + } + for (int s = 0; s < image->samples_per_pixel; s++) { + if (image->white_level[s] == -1) { + // Set white level with (2 ** BitsPerSample) according to the DNG spec. + if (image->bits_per_sample_original == 0) { + if (err) { + (*err) += "Bits per sample of image has to be > 0.\n"; + } + return false; + } + + if (image->bits_per_sample_original >= + 32) { // workaround for 32bit floating point TIFF. + image->white_level[s] = -1; + } else { + if (image->bits_per_sample_original >= 32) { + if (err) { + (*err) += "Cannot handle >= 32 bits per sample.\n"; + } + return false; + } + + image->white_level[s] = (1 << image->bits_per_sample_original) - 1; + } + } + + // Shrink value when TIFF tag white level is larger than (2**bps) + // e.g. Set to 4096 if TIFF white_balance tag has 65535 but bps == 12 + // FIXME: Is this ok according to DNG spec? + if ((image->bits_per_sample_original > 0) && + (image->bits_per_sample_original < 30)) { + if (image->white_level[s] >= (1 << image->bits_per_sample_original)) { + image->white_level[s] = (1 << image->bits_per_sample_original) - 1; + } + } + } + } + + return ret ? true : false; +} + +bool IsDNGFromMemory(const char* mem, unsigned int size, std::string* msg) { + if ((mem == NULL) || (size < 32)) { + if (msg) { + (*msg) = "Invalid argument. argument is null or invalid.\n"; + } + return false; + } + + const unsigned short magic = *(reinterpret_cast<const unsigned short*>(mem)); + + if (magic == 0x4949) { + // might be TIFF(DNG). + } else if (magic == 0x4d4d) { + // might be TIFF(DNG, bigendian). + if (msg) { + (*msg) = "DNG is big endian"; + } + } else { + return false; + } + + return true; +} + +bool IsDNG(const char* filename, std::string* msg) { + std::stringstream ss; + + FILE* fp = NULL; +#if defined(_WIN32) + +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = _wfopen_s(&fp, UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + if (msg) { + (*msg) += "Error opening file: " + std::string(filename) + "(errno " + + std::to_string(errcode) + ")\n"; + } + return false; + } +#else + // Unknown compiler + fp = fopen(filename, "rb"); +#endif + +#else + fp = fopen(filename, "rb"); +#endif + if (!fp) { + ss << "File not found or cannot open file " << filename << std::endl; + if (msg) { + (*msg) = ss.str(); + } + return false; + } + + if (0 != fseek(fp, 0, SEEK_END)) { + if (msg) { + (*msg) = "Error seeking.\n"; + } + return false; + } + + size_t file_size = static_cast<size_t>(ftell(fp)); + + std::vector<unsigned char> whole_data; + { + whole_data.resize(file_size); + fseek(fp, 0, SEEK_SET); + size_t read_len = fread(whole_data.data(), 1, file_size, fp); + if (read_len != file_size) { + if (msg) { + (*msg) += "Unexpected file size.\n"; + } + return false; + } + + fseek(fp, 0, SEEK_SET); + } + fclose(fp); + + return IsDNGFromMemory(reinterpret_cast<const char*>(whole_data.data()), + static_cast<unsigned int>(whole_data.size()), msg); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +} // namespace tinydng + +#endif + +#endif // TINY_DNG_LOADER_H_ diff --git a/external/tiny_exr/CMakeLists.txt b/external/tiny_exr/CMakeLists.txt new file mode 100644 index 00000000..0648eb19 --- /dev/null +++ b/external/tiny_exr/CMakeLists.txt @@ -0,0 +1,9 @@ +## Copyright 2023 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +add_library(tiny_exr STATIC tinyexr_impl.cpp) + +target_include_directories(tiny_exr +PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> +) diff --git a/external/tiny_exr/tinyexr.h b/external/tiny_exr/tinyexr.h new file mode 100644 index 00000000..3613aaa8 --- /dev/null +++ b/external/tiny_exr/tinyexr.h @@ -0,0 +1,9226 @@ +#ifndef TINYEXR_H_ +#define TINYEXR_H_ +/* +Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Syoyo Fujita nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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. +*/ + +// TinyEXR contains some OpenEXR code, which is licensed under ------------ + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +// End of OpenEXR license ------------------------------------------------- + + +// +// +// Do this: +// #define TINYEXR_IMPLEMENTATION +// before you include this file in *one* C or C++ file to create the +// implementation. +// +// // i.e. it should look like this: +// #include ... +// #include ... +// #include ... +// #define TINYEXR_IMPLEMENTATION +// #include "tinyexr.h" +// +// + +#include <stddef.h> // for size_t +#include <stdint.h> // guess stdint.h is available(C99) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ + defined(__i386) || defined(__i486__) || defined(__i486) || \ + defined(i386) || defined(__ia64__) || defined(__x86_64__) +#define TINYEXR_X86_OR_X64_CPU 1 +#else +#define TINYEXR_X86_OR_X64_CPU 0 +#endif + +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || TINYEXR_X86_OR_X64_CPU +#define TINYEXR_LITTLE_ENDIAN 1 +#else +#define TINYEXR_LITTLE_ENDIAN 0 +#endif + +// Use miniz or not to decode ZIP format pixel. Linking with zlib +// required if this flag is 0 and TINYEXR_USE_STB_ZLIB is 0. +#ifndef TINYEXR_USE_MINIZ +#define TINYEXR_USE_MINIZ (1) +#endif + +// Use the ZIP implementation of stb_image.h and stb_image_write.h. +#ifndef TINYEXR_USE_STB_ZLIB +#define TINYEXR_USE_STB_ZLIB (0) +#endif + +// Disable PIZ compression when applying cpplint. +#ifndef TINYEXR_USE_PIZ +#define TINYEXR_USE_PIZ (1) +#endif + +#ifndef TINYEXR_USE_ZFP +#define TINYEXR_USE_ZFP (0) // TinyEXR extension. +// http://computation.llnl.gov/projects/floating-point-compression +#endif + +#ifndef TINYEXR_USE_THREAD +#define TINYEXR_USE_THREAD (0) // No threaded loading. +// http://computation.llnl.gov/projects/floating-point-compression +#endif + +#ifndef TINYEXR_USE_OPENMP +#ifdef _OPENMP +#define TINYEXR_USE_OPENMP (1) +#else +#define TINYEXR_USE_OPENMP (0) +#endif +#endif + +#define TINYEXR_SUCCESS (0) +#define TINYEXR_ERROR_INVALID_MAGIC_NUMBER (-1) +#define TINYEXR_ERROR_INVALID_EXR_VERSION (-2) +#define TINYEXR_ERROR_INVALID_ARGUMENT (-3) +#define TINYEXR_ERROR_INVALID_DATA (-4) +#define TINYEXR_ERROR_INVALID_FILE (-5) +#define TINYEXR_ERROR_INVALID_PARAMETER (-6) +#define TINYEXR_ERROR_CANT_OPEN_FILE (-7) +#define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-8) +#define TINYEXR_ERROR_INVALID_HEADER (-9) +#define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-10) +#define TINYEXR_ERROR_CANT_WRITE_FILE (-11) +#define TINYEXR_ERROR_SERIALIZATION_FAILED (-12) +#define TINYEXR_ERROR_LAYER_NOT_FOUND (-13) +#define TINYEXR_ERROR_DATA_TOO_LARGE (-14) + +// @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf } + +// pixel type: possible values are: UINT = 0 HALF = 1 FLOAT = 2 +#define TINYEXR_PIXELTYPE_UINT (0) +#define TINYEXR_PIXELTYPE_HALF (1) +#define TINYEXR_PIXELTYPE_FLOAT (2) + +#define TINYEXR_MAX_HEADER_ATTRIBUTES (1024) +#define TINYEXR_MAX_CUSTOM_ATTRIBUTES (128) + +#define TINYEXR_COMPRESSIONTYPE_NONE (0) +#define TINYEXR_COMPRESSIONTYPE_RLE (1) +#define TINYEXR_COMPRESSIONTYPE_ZIPS (2) +#define TINYEXR_COMPRESSIONTYPE_ZIP (3) +#define TINYEXR_COMPRESSIONTYPE_PIZ (4) +#define TINYEXR_COMPRESSIONTYPE_ZFP (128) // TinyEXR extension + +#define TINYEXR_ZFP_COMPRESSIONTYPE_RATE (0) +#define TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION (1) +#define TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY (2) + +#define TINYEXR_TILE_ONE_LEVEL (0) +#define TINYEXR_TILE_MIPMAP_LEVELS (1) +#define TINYEXR_TILE_RIPMAP_LEVELS (2) + +#define TINYEXR_TILE_ROUND_DOWN (0) +#define TINYEXR_TILE_ROUND_UP (1) + +typedef struct TEXRVersion { + int version; // this must be 2 + // tile format image; + // not zero for only a single-part "normal" tiled file (according to spec.) + int tiled; + int long_name; // long name attribute + // deep image(EXR 2.0); + // for a multi-part file, indicates that at least one part is of type deep* (according to spec.) + int non_image; + int multipart; // multi-part(EXR 2.0) +} EXRVersion; + +typedef struct TEXRAttribute { + char name[256]; // name and type are up to 255 chars long. + char type[256]; + unsigned char *value; // uint8_t* + int size; + int pad0; +} EXRAttribute; + +typedef struct TEXRChannelInfo { + char name[256]; // less than 255 bytes long + int pixel_type; + int x_sampling; + int y_sampling; + unsigned char p_linear; + unsigned char pad[3]; +} EXRChannelInfo; + +typedef struct TEXRTile { + int offset_x; + int offset_y; + int level_x; + int level_y; + + int width; // actual width in a tile. + int height; // actual height int a tile. + + unsigned char **images; // image[channels][pixels] +} EXRTile; + +typedef struct TEXRBox2i { + int min_x; + int min_y; + int max_x; + int max_y; +} EXRBox2i; + +typedef struct TEXRHeader { + float pixel_aspect_ratio; + int line_order; + EXRBox2i data_window; + EXRBox2i display_window; + float screen_window_center[2]; + float screen_window_width; + + int chunk_count; + + // Properties for tiled format(`tiledesc`). + int tiled; + int tile_size_x; + int tile_size_y; + int tile_level_mode; + int tile_rounding_mode; + + int long_name; + // for a single-part file, agree with the version field bit 11 + // for a multi-part file, it is consistent with the type of part + int non_image; + int multipart; + unsigned int header_len; + + // Custom attributes(exludes required attributes(e.g. `channels`, + // `compression`, etc) + int num_custom_attributes; + EXRAttribute *custom_attributes; // array of EXRAttribute. size = + // `num_custom_attributes`. + + EXRChannelInfo *channels; // [num_channels] + + int *pixel_types; // Loaded pixel type(TINYEXR_PIXELTYPE_*) of `images` for + // each channel. This is overwritten with `requested_pixel_types` when + // loading. + int num_channels; + + int compression_type; // compression type(TINYEXR_COMPRESSIONTYPE_*) + int *requested_pixel_types; // Filled initially by + // ParseEXRHeaderFrom(Meomory|File), then users + // can edit it(only valid for HALF pixel type + // channel) + // name attribute required for multipart files; + // must be unique and non empty (according to spec.); + // use EXRSetNameAttr for setting value; + // max 255 character allowed - excluding terminating zero + char name[256]; +} EXRHeader; + +typedef struct TEXRMultiPartHeader { + int num_headers; + EXRHeader *headers; + +} EXRMultiPartHeader; + +typedef struct TEXRImage { + EXRTile *tiles; // Tiled pixel data. The application must reconstruct image + // from tiles manually. NULL if scanline format. + struct TEXRImage* next_level; // NULL if scanline format or image is the last level. + int level_x; // x level index + int level_y; // y level index + + unsigned char **images; // image[channels][pixels]. NULL if tiled format. + + int width; + int height; + int num_channels; + + // Properties for tile format. + int num_tiles; + +} EXRImage; + +typedef struct TEXRMultiPartImage { + int num_images; + EXRImage *images; + +} EXRMultiPartImage; + +typedef struct TDeepImage { + const char **channel_names; + float ***image; // image[channels][scanlines][samples] + int **offset_table; // offset_table[scanline][offsets] + int num_channels; + int width; + int height; + int pad0; +} DeepImage; + +// @deprecated { For backward compatibility. Not recommended to use. } +// Loads single-frame OpenEXR image. Assume EXR image contains A(single channel +// alpha) or RGB(A) channels. +// Application must free image data as returned by `out_rgba` +// Result image format is: float x RGBA x width x hight +// Returns negative value and may set error string in `err` when there's an +// error +extern int LoadEXR(float **out_rgba, int *width, int *height, + const char *filename, const char **err); + +// Loads single-frame OpenEXR image by specifying layer name. Assume EXR image +// contains A(single channel alpha) or RGB(A) channels. Application must free +// image data as returned by `out_rgba` Result image format is: float x RGBA x +// width x hight Returns negative value and may set error string in `err` when +// there's an error When the specified layer name is not found in the EXR file, +// the function will return `TINYEXR_ERROR_LAYER_NOT_FOUND`. +extern int LoadEXRWithLayer(float **out_rgba, int *width, int *height, + const char *filename, const char *layer_name, + const char **err); + +// +// Get layer infos from EXR file. +// +// @param[out] layer_names List of layer names. Application must free memory +// after using this. +// @param[out] num_layers The number of layers +// @param[out] err Error string(will be filled when the function returns error +// code). Free it using FreeEXRErrorMessage after using this value. +// +// @return TINYEXR_SUCCEES upon success. +// +extern int EXRLayers(const char *filename, const char **layer_names[], + int *num_layers, const char **err); + +// @deprecated +// Simple wrapper API for ParseEXRHeaderFromFile. +// checking given file is a EXR file(by just look up header) +// @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for +// others +extern int IsEXR(const char *filename); + +// Simple wrapper API for ParseEXRHeaderFromMemory. +// Check if given data is a EXR image(by just looking up a header section) +// @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for +// others +extern int IsEXRFromMemory(const unsigned char *memory, size_t size); + +// @deprecated +// Saves single-frame OpenEXR image to a buffer. Assume EXR image contains RGB(A) channels. +// components must be 1(Grayscale), 3(RGB) or 4(RGBA). +// Input image format is: `float x width x height`, or `float x RGB(A) x width x +// hight` +// Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero +// value. +// Save image as fp32(FLOAT) format when `save_as_fp16` is 0. +// Use ZIP compression by default. +// `buffer` is the pointer to write EXR data. +// Memory for `buffer` is allocated internally in SaveEXRToMemory. +// Returns the data size of EXR file when the value is positive(up to 2GB EXR data). +// Returns negative value and may set error string in `err` when there's an +// error +extern int SaveEXRToMemory(const float *data, const int width, const int height, + const int components, const int save_as_fp16, + const unsigned char **buffer, const char **err); + +// @deprecated { Not recommended, but handy to use. } +// Saves single-frame OpenEXR image to a buffer. Assume EXR image contains RGB(A) channels. +// components must be 1(Grayscale), 3(RGB) or 4(RGBA). +// Input image format is: `float x width x height`, or `float x RGB(A) x width x +// hight` +// Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero +// value. +// Save image as fp32(FLOAT) format when `save_as_fp16` is 0. +// Use ZIP compression by default. +// Returns TINYEXR_SUCCEES(0) when success. +// Returns negative value and may set error string in `err` when there's an +// error +extern int SaveEXR(const float *data, const int width, const int height, + const int components, const int save_as_fp16, + const char *filename, const char **err); + +// Returns the number of resolution levels of the image (including the base) +extern int EXRNumLevels(const EXRImage* exr_image); + +// Initialize EXRHeader struct +extern void InitEXRHeader(EXRHeader *exr_header); + +// Set name attribute of EXRHeader struct (it makes a copy) +extern void EXRSetNameAttr(EXRHeader *exr_header, const char* name); + +// Initialize EXRImage struct +extern void InitEXRImage(EXRImage *exr_image); + +// Frees internal data of EXRHeader struct +extern int FreeEXRHeader(EXRHeader *exr_header); + +// Frees internal data of EXRImage struct +extern int FreeEXRImage(EXRImage *exr_image); + +// Frees error message +extern void FreeEXRErrorMessage(const char *msg); + +// Parse EXR version header of a file. +extern int ParseEXRVersionFromFile(EXRVersion *version, const char *filename); + +// Parse EXR version header from memory-mapped EXR data. +extern int ParseEXRVersionFromMemory(EXRVersion *version, + const unsigned char *memory, size_t size); + +// Parse single-part OpenEXR header from a file and initialize `EXRHeader`. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version, + const char *filename, const char **err); + +// Parse single-part OpenEXR header from a memory and initialize `EXRHeader`. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int ParseEXRHeaderFromMemory(EXRHeader *header, + const EXRVersion *version, + const unsigned char *memory, size_t size, + const char **err); + +// Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*` +// array. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers, + int *num_headers, + const EXRVersion *version, + const char *filename, + const char **err); + +// Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*` +// array +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers, + int *num_headers, + const EXRVersion *version, + const unsigned char *memory, + size_t size, const char **err); + +// Loads single-part OpenEXR image from a file. +// Application must setup `ParseEXRHeaderFromFile` before calling this function. +// Application can free EXRImage using `FreeEXRImage` +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header, + const char *filename, const char **err); + +// Loads single-part OpenEXR image from a memory. +// Application must setup `EXRHeader` with +// `ParseEXRHeaderFromMemory` before calling this function. +// Application can free EXRImage using `FreeEXRImage` +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header, + const unsigned char *memory, + const size_t size, const char **err); + +// Loads multi-part OpenEXR image from a file. +// Application must setup `ParseEXRMultipartHeaderFromFile` before calling this +// function. +// Application can free EXRImage using `FreeEXRImage` +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int LoadEXRMultipartImageFromFile(EXRImage *images, + const EXRHeader **headers, + unsigned int num_parts, + const char *filename, + const char **err); + +// Loads multi-part OpenEXR image from a memory. +// Application must setup `EXRHeader*` array with +// `ParseEXRMultipartHeaderFromMemory` before calling this function. +// Application can free EXRImage using `FreeEXRImage` +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int LoadEXRMultipartImageFromMemory(EXRImage *images, + const EXRHeader **headers, + unsigned int num_parts, + const unsigned char *memory, + const size_t size, const char **err); + +// Saves multi-channel, single-frame OpenEXR image to a file. +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int SaveEXRImageToFile(const EXRImage *image, + const EXRHeader *exr_header, const char *filename, + const char **err); + +// Saves multi-channel, single-frame OpenEXR image to a memory. +// Image is compressed using EXRImage.compression value. +// Return the number of bytes if success. +// Return zero and will set error string in `err` when there's an +// error. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern size_t SaveEXRImageToMemory(const EXRImage *image, + const EXRHeader *exr_header, + unsigned char **memory, const char **err); + +// Saves multi-channel, multi-frame OpenEXR image to a memory. +// Image is compressed using EXRImage.compression value. +// File global attributes (eg. display_window) must be set in the first header. +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int SaveEXRMultipartImageToFile(const EXRImage *images, + const EXRHeader **exr_headers, + unsigned int num_parts, + const char *filename, const char **err); + +// Saves multi-channel, multi-frame OpenEXR image to a memory. +// Image is compressed using EXRImage.compression value. +// File global attributes (eg. display_window) must be set in the first header. +// Return the number of bytes if success. +// Return zero and will set error string in `err` when there's an +// error. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern size_t SaveEXRMultipartImageToMemory(const EXRImage *images, + const EXRHeader **exr_headers, + unsigned int num_parts, + unsigned char **memory, const char **err); +// Loads single-frame OpenEXR deep image. +// Application must free memory of variables in DeepImage(image, offset_table) +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int LoadDeepEXR(DeepImage *out_image, const char *filename, + const char **err); + +// NOT YET IMPLEMENTED: +// Saves single-frame OpenEXR deep image. +// Returns negative value and may set error string in `err` when there's an +// error +// extern int SaveDeepEXR(const DeepImage *in_image, const char *filename, +// const char **err); + +// NOT YET IMPLEMENTED: +// Loads multi-part OpenEXR deep image. +// Application must free memory of variables in DeepImage(image, offset_table) +// extern int LoadMultiPartDeepEXR(DeepImage **out_image, int num_parts, const +// char *filename, +// const char **err); + +// For emscripten. +// Loads single-frame OpenEXR image from memory. Assume EXR image contains +// RGB(A) channels. +// Returns negative value and may set error string in `err` when there's an +// error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() +extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, + const unsigned char *memory, size_t size, + const char **err); + +#ifdef __cplusplus +} +#endif + +#endif // TINYEXR_H_ + +#ifdef TINYEXR_IMPLEMENTATION +#ifndef TINYEXR_IMPLEMENTATION_DEFINED +#define TINYEXR_IMPLEMENTATION_DEFINED + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include <windows.h> // for UTF-8 and memory-mapping +#define TINYEXR_USE_WIN32_MMAP (1) + +#elif defined(__linux__) || defined(__unix__) +#include <fcntl.h> // for open() +#include <sys/mman.h> // for memory-mapping +#include <sys/stat.h> // for stat +#include <unistd.h> // for close() +#define TINYEXR_USE_POSIX_MMAP (1) +#endif + +#include <algorithm> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <sstream> + +//#include <iostream> // debug + +#include <limits> +#include <string> +#include <vector> +#include <set> + +// https://stackoverflow.com/questions/5047971/how-do-i-check-for-c11-support +#if __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#define TINYEXR_HAS_CXX11 (1) +// C++11 +#include <cstdint> + +#if TINYEXR_USE_THREAD +#include <atomic> +#include <thread> +#endif + +#else // __cplusplus > 199711L +#define TINYEXR_HAS_CXX11 (0) +#endif // __cplusplus > 199711L + +#if TINYEXR_USE_OPENMP +#include <omp.h> +#endif + +#if TINYEXR_USE_MINIZ +#include <miniz.h> +#else +// Issue #46. Please include your own zlib-compatible API header before +// including `tinyexr.h` +//#include "zlib.h" +#endif + +#if TINYEXR_USE_STB_ZLIB +// Since we don't know where a project has stb_image.h and stb_image_write.h +// and whether they are in the include path, we don't include them here, and +// instead declare the two relevant functions manually. +// from stb_image.h: +extern "C" int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); +// from stb_image_write.h: +extern "C" unsigned char *stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality); +#endif + +#if TINYEXR_USE_ZFP + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" +#endif + +#include "zfp.h" + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +// cond: conditional expression +// msg: std::string +// err: std::string* +#define TINYEXR_CHECK_AND_RETURN_MSG(cond, msg, err) do { \ + if (!(cond)) { \ + if (!err) { \ + std::ostringstream ss_e; \ + ss_e << __func__ << "():" << __LINE__ << msg << "\n"; \ + (*err) += ss_e.str(); \ + } \ + return false;\ + } \ + } while(0) + +// no error message. +#define TINYEXR_CHECK_AND_RETURN_C(cond, retcode) do { \ + if (!(cond)) { \ + return retcode; \ + } \ + } while(0) + +namespace tinyexr { + +#if __cplusplus > 199711L +// C++11 +typedef uint64_t tinyexr_uint64; +typedef int64_t tinyexr_int64; +#else +// Although `long long` is not a standard type pre C++11, assume it is defined +// as a compiler's extension. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif +typedef unsigned long long tinyexr_uint64; +typedef long long tinyexr_int64; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif + +// static bool IsBigEndian(void) { +// union { +// unsigned int i; +// char c[4]; +// } bint = {0x01020304}; +// +// return bint.c[0] == 1; +//} + +static void SetErrorMessage(const std::string &msg, const char **err) { + if (err) { +#ifdef _WIN32 + (*err) = _strdup(msg.c_str()); +#else + (*err) = strdup(msg.c_str()); +#endif + } +} + +#if 0 +static void SetWarningMessage(const std::string &msg, const char **warn) { + if (warn) { +#ifdef _WIN32 + (*warn) = _strdup(msg.c_str()); +#else + (*warn) = strdup(msg.c_str()); +#endif + } +} +#endif + +static const int kEXRVersionSize = 8; + +static void cpy2(unsigned short *dst_val, const unsigned short *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; +} + +static void swap2(unsigned short *val) { +#ifdef TINYEXR_LITTLE_ENDIAN + (void)val; +#else + unsigned short tmp = *val; + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[1]; + dst[1] = src[0]; +#endif +} + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +static void cpy4(int *dst_val, const int *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +static void cpy4(unsigned int *dst_val, const unsigned int *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +static void cpy4(float *dst_val, const float *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +static void swap4(unsigned int *val) { +#ifdef TINYEXR_LITTLE_ENDIAN + (void)val; +#else + unsigned int tmp = *val; + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +#endif +} + +static void swap4(int *val) { +#ifdef TINYEXR_LITTLE_ENDIAN + (void)val; +#else + int tmp = *val; + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +#endif +} + +static void swap4(float *val) { +#ifdef TINYEXR_LITTLE_ENDIAN + (void)val; +#else + float tmp = *val; + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +#endif +} + +#if 0 +static void cpy8(tinyexr::tinyexr_uint64 *dst_val, const tinyexr::tinyexr_uint64 *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; +} +#endif + +static void swap8(tinyexr::tinyexr_uint64 *val) { +#ifdef TINYEXR_LITTLE_ENDIAN + (void)val; +#else + tinyexr::tinyexr_uint64 tmp = (*val); + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; +#endif +} + +// https://gist.github.com/rygorous/2156668 +union FP32 { + unsigned int u; + float f; + struct { +#if TINYEXR_LITTLE_ENDIAN + unsigned int Mantissa : 23; + unsigned int Exponent : 8; + unsigned int Sign : 1; +#else + unsigned int Sign : 1; + unsigned int Exponent : 8; + unsigned int Mantissa : 23; +#endif + } s; +}; + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +union FP16 { + unsigned short u; + struct { +#if TINYEXR_LITTLE_ENDIAN + unsigned int Mantissa : 10; + unsigned int Exponent : 5; + unsigned int Sign : 1; +#else + unsigned int Sign : 1; + unsigned int Exponent : 5; + unsigned int Mantissa : 10; +#endif + } s; +}; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +static FP32 half_to_float(FP16 h) { + static const FP32 magic = {113 << 23}; + static const unsigned int shifted_exp = 0x7c00 + << 13; // exponent mask after shift + FP32 o; + + o.u = (h.u & 0x7fffU) << 13U; // exponent/mantissa bits + unsigned int exp_ = shifted_exp & o.u; // just the exponent + o.u += (127 - 15) << 23; // exponent adjust + + // handle exponent special cases + if (exp_ == shifted_exp) // Inf/NaN? + o.u += (128 - 16) << 23; // extra exp adjust + else if (exp_ == 0) // Zero/Denormal? + { + o.u += 1 << 23; // extra exp adjust + o.f -= magic.f; // renormalize + } + + o.u |= (h.u & 0x8000U) << 16U; // sign bit + return o; +} + +static FP16 float_to_half_full(FP32 f) { + FP16 o = {0}; + + // Based on ISPC reference code (with minor modifications) + if (f.s.Exponent == 0) // Signed zero/denormal (which will underflow) + o.s.Exponent = 0; + else if (f.s.Exponent == 255) // Inf or NaN (all exponent bits set) + { + o.s.Exponent = 31; + o.s.Mantissa = f.s.Mantissa ? 0x200 : 0; // NaN->qNaN and Inf->Inf + } else // Normalized number + { + // Exponent unbias the single, then bias the halfp + int newexp = f.s.Exponent - 127 + 15; + if (newexp >= 31) // Overflow, return signed infinity + o.s.Exponent = 31; + else if (newexp <= 0) // Underflow + { + if ((14 - newexp) <= 24) // Mantissa might be non-zero + { + unsigned int mant = f.s.Mantissa | 0x800000; // Hidden 1 bit + o.s.Mantissa = mant >> (14 - newexp); + if ((mant >> (13 - newexp)) & 1) // Check for rounding + o.u++; // Round, might overflow into exp bit, but this is OK + } + } else { + o.s.Exponent = static_cast<unsigned int>(newexp); + o.s.Mantissa = f.s.Mantissa >> 13; + if (f.s.Mantissa & 0x1000) // Check for rounding + o.u++; // Round, might overflow to inf, this is OK + } + } + + o.s.Sign = f.s.Sign; + return o; +} + +// NOTE: From OpenEXR code +// #define IMF_INCREASING_Y 0 +// #define IMF_DECREASING_Y 1 +// #define IMF_RAMDOM_Y 2 +// +// #define IMF_NO_COMPRESSION 0 +// #define IMF_RLE_COMPRESSION 1 +// #define IMF_ZIPS_COMPRESSION 2 +// #define IMF_ZIP_COMPRESSION 3 +// #define IMF_PIZ_COMPRESSION 4 +// #define IMF_PXR24_COMPRESSION 5 +// #define IMF_B44_COMPRESSION 6 +// #define IMF_B44A_COMPRESSION 7 + +#ifdef __clang__ +#pragma clang diagnostic push + +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + +#endif + +static const char *ReadString(std::string *s, const char *ptr, size_t len) { + // Read untile NULL(\0). + const char *p = ptr; + const char *q = ptr; + while ((size_t(q - ptr) < len) && (*q) != 0) { + q++; + } + + if (size_t(q - ptr) >= len) { + (*s).clear(); + return NULL; + } + + (*s) = std::string(p, q); + + return q + 1; // skip '\0' +} + +static bool ReadAttribute(std::string *name, std::string *type, + std::vector<unsigned char> *data, size_t *marker_size, + const char *marker, size_t size) { + size_t name_len = strnlen(marker, size); + if (name_len == size) { + // String does not have a terminating character. + return false; + } + *name = std::string(marker, name_len); + + marker += name_len + 1; + size -= name_len + 1; + + size_t type_len = strnlen(marker, size); + if (type_len == size) { + return false; + } + *type = std::string(marker, type_len); + + marker += type_len + 1; + size -= type_len + 1; + + if (size < sizeof(uint32_t)) { + return false; + } + + uint32_t data_len; + memcpy(&data_len, marker, sizeof(uint32_t)); + tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); + + if (data_len == 0) { + if ((*type).compare("string") == 0) { + // Accept empty string attribute. + + marker += sizeof(uint32_t); + size -= sizeof(uint32_t); + + *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t); + + data->resize(1); + (*data)[0] = '\0'; + + return true; + } else { + return false; + } + } + + marker += sizeof(uint32_t); + size -= sizeof(uint32_t); + + if (size < data_len) { + return false; + } + + data->resize(static_cast<size_t>(data_len)); + memcpy(&data->at(0), marker, static_cast<size_t>(data_len)); + + *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t) + data_len; + return true; +} + +static void WriteAttributeToMemory(std::vector<unsigned char> *out, + const char *name, const char *type, + const unsigned char *data, int len) { + out->insert(out->end(), name, name + strlen(name) + 1); + out->insert(out->end(), type, type + strlen(type) + 1); + + int outLen = len; + tinyexr::swap4(&outLen); + out->insert(out->end(), reinterpret_cast<unsigned char *>(&outLen), + reinterpret_cast<unsigned char *>(&outLen) + sizeof(int)); + out->insert(out->end(), data, data + len); +} + +typedef struct TChannelInfo { + std::string name; // less than 255 bytes long + int pixel_type; + int requested_pixel_type; + int x_sampling; + int y_sampling; + unsigned char p_linear; + unsigned char pad[3]; +} ChannelInfo; + +typedef struct { + int min_x; + int min_y; + int max_x; + int max_y; +} Box2iInfo; + +struct HeaderInfo { + std::vector<tinyexr::ChannelInfo> channels; + std::vector<EXRAttribute> attributes; + + Box2iInfo data_window; + int line_order; + Box2iInfo display_window; + float screen_window_center[2]; + float screen_window_width; + float pixel_aspect_ratio; + + int chunk_count; + + // Tiled format + int tiled; // Non-zero if the part is tiled. + int tile_size_x; + int tile_size_y; + int tile_level_mode; + int tile_rounding_mode; + + unsigned int header_len; + + int compression_type; + + // required for multi-part or non-image files + std::string name; + // required for multi-part or non-image files + std::string type; + + void clear() { + channels.clear(); + attributes.clear(); + + data_window.min_x = 0; + data_window.min_y = 0; + data_window.max_x = 0; + data_window.max_y = 0; + line_order = 0; + display_window.min_x = 0; + display_window.min_y = 0; + display_window.max_x = 0; + display_window.max_y = 0; + screen_window_center[0] = 0.0f; + screen_window_center[1] = 0.0f; + screen_window_width = 0.0f; + pixel_aspect_ratio = 0.0f; + + chunk_count = 0; + + // Tiled format + tiled = 0; + tile_size_x = 0; + tile_size_y = 0; + tile_level_mode = 0; + tile_rounding_mode = 0; + + header_len = 0; + compression_type = 0; + + name.clear(); + type.clear(); + } +}; + +static bool ReadChannelInfo(std::vector<ChannelInfo> &channels, + const std::vector<unsigned char> &data) { + const char *p = reinterpret_cast<const char *>(&data.at(0)); + + for (;;) { + if ((*p) == 0) { + break; + } + ChannelInfo info; + info.requested_pixel_type = 0; + + tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) - + (p - reinterpret_cast<const char *>(data.data())); + if (data_len < 0) { + return false; + } + + p = ReadString(&info.name, p, size_t(data_len)); + if ((p == NULL) && (info.name.empty())) { + // Buffer overrun. Issue #51. + return false; + } + + const unsigned char *data_end = + reinterpret_cast<const unsigned char *>(p) + 16; + if (data_end >= (data.data() + data.size())) { + return false; + } + + memcpy(&info.pixel_type, p, sizeof(int)); + p += 4; + info.p_linear = static_cast<unsigned char>(p[0]); // uchar + p += 1 + 3; // reserved: uchar[3] + memcpy(&info.x_sampling, p, sizeof(int)); // int + p += 4; + memcpy(&info.y_sampling, p, sizeof(int)); // int + p += 4; + + tinyexr::swap4(&info.pixel_type); + tinyexr::swap4(&info.x_sampling); + tinyexr::swap4(&info.y_sampling); + + channels.push_back(info); + } + + return true; +} + +static void WriteChannelInfo(std::vector<unsigned char> &data, + const std::vector<ChannelInfo> &channels) { + size_t sz = 0; + + // Calculate total size. + for (size_t c = 0; c < channels.size(); c++) { + sz += channels[c].name.length() + 1; // +1 for \0 + sz += 16; // 4 * int + } + data.resize(sz + 1); + + unsigned char *p = &data.at(0); + + for (size_t c = 0; c < channels.size(); c++) { + memcpy(p, channels[c].name.c_str(), channels[c].name.length()); + p += channels[c].name.length(); + (*p) = '\0'; + p++; + + int pixel_type = channels[c].requested_pixel_type; + int x_sampling = channels[c].x_sampling; + int y_sampling = channels[c].y_sampling; + tinyexr::swap4(&pixel_type); + tinyexr::swap4(&x_sampling); + tinyexr::swap4(&y_sampling); + + memcpy(p, &pixel_type, sizeof(int)); + p += sizeof(int); + + (*p) = channels[c].p_linear; + p += 4; + + memcpy(p, &x_sampling, sizeof(int)); + p += sizeof(int); + + memcpy(p, &y_sampling, sizeof(int)); + p += sizeof(int); + } + + (*p) = '\0'; +} + +static bool CompressZip(unsigned char *dst, + tinyexr::tinyexr_uint64 &compressedSize, + const unsigned char *src, unsigned long src_size) { + std::vector<unsigned char> tmpBuf(src_size); + + // + // Apply EXR-specific? postprocess. Grabbed from OpenEXR's + // ImfZipCompressor.cpp + // + + // + // Reorder the pixel data. + // + + const char *srcPtr = reinterpret_cast<const char *>(src); + + { + char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0)); + char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2; + const char *stop = srcPtr + src_size; + + for (;;) { + if (srcPtr < stop) + *(t1++) = *(srcPtr++); + else + break; + + if (srcPtr < stop) + *(t2++) = *(srcPtr++); + else + break; + } + } + + // + // Predictor. + // + + { + unsigned char *t = &tmpBuf.at(0) + 1; + unsigned char *stop = &tmpBuf.at(0) + src_size; + int p = t[-1]; + + while (t < stop) { + int d = int(t[0]) - p + (128 + 256); + p = t[0]; + t[0] = static_cast<unsigned char>(d); + ++t; + } + } + +#if TINYEXR_USE_MINIZ + // + // Compress the data using miniz + // + + mz_ulong outSize = mz_compressBound(src_size); + int ret = mz_compress( + dst, &outSize, static_cast<const unsigned char *>(&tmpBuf.at(0)), + src_size); + if (ret != MZ_OK) { + return false; + } + + compressedSize = outSize; +#elif TINYEXR_USE_STB_ZLIB + int outSize; + unsigned char* ret = stbi_zlib_compress(const_cast<unsigned char*>(&tmpBuf.at(0)), src_size, &outSize, 8); + if (!ret) { + return false; + } + memcpy(dst, ret, outSize); + free(ret); + + compressedSize = outSize; +#else + uLong outSize = compressBound(static_cast<uLong>(src_size)); + int ret = compress(dst, &outSize, static_cast<const Bytef *>(&tmpBuf.at(0)), + src_size); + if (ret != Z_OK) { + return false; + } + + compressedSize = outSize; +#endif + + // Use uncompressed data when compressed data is larger than uncompressed. + // (Issue 40) + if (compressedSize >= src_size) { + compressedSize = src_size; + memcpy(dst, src, src_size); + } + + return true; +} + +static bool DecompressZip(unsigned char *dst, + unsigned long *uncompressed_size /* inout */, + const unsigned char *src, unsigned long src_size) { + if ((*uncompressed_size) == src_size) { + // Data is not compressed(Issue 40). + memcpy(dst, src, src_size); + return true; + } + std::vector<unsigned char> tmpBuf(*uncompressed_size); + +#if TINYEXR_USE_MINIZ + int ret = + mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); + if (MZ_OK != ret) { + return false; + } +#elif TINYEXR_USE_STB_ZLIB + int ret = stbi_zlib_decode_buffer(reinterpret_cast<char*>(&tmpBuf.at(0)), + *uncompressed_size, reinterpret_cast<const char*>(src), src_size); + if (ret < 0) { + return false; + } +#else + int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); + if (Z_OK != ret) { + return false; + } +#endif + + // + // Apply EXR-specific? postprocess. Grabbed from OpenEXR's + // ImfZipCompressor.cpp + // + + // Predictor. + { + unsigned char *t = &tmpBuf.at(0) + 1; + unsigned char *stop = &tmpBuf.at(0) + (*uncompressed_size); + + while (t < stop) { + int d = int(t[-1]) + int(t[0]) - 128; + t[0] = static_cast<unsigned char>(d); + ++t; + } + } + + // Reorder the pixel data. + { + const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0)); + const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) + + (*uncompressed_size + 1) / 2; + char *s = reinterpret_cast<char *>(dst); + char *stop = s + (*uncompressed_size); + + for (;;) { + if (s < stop) + *(s++) = *(t1++); + else + break; + + if (s < stop) + *(s++) = *(t2++); + else + break; + } + } + + return true; +} + +// RLE code from OpenEXR -------------------------------------- + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-conversion" +#if __has_warning("-Wextra-semi-stmt") +#pragma clang diagnostic ignored "-Wextra-semi-stmt" +#endif +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4204) // nonstandard extension used : non-constant + // aggregate initializer (also supported by GNU + // C and C99, so no big deal) +#pragma warning(disable : 4244) // 'initializing': conversion from '__int64' to + // 'int', possible loss of data +#pragma warning(disable : 4267) // 'argument': conversion from '__int64' to + // 'int', possible loss of data +#pragma warning(disable : 4996) // 'strdup': The POSIX name for this item is + // deprecated. Instead, use the ISO C and C++ + // conformant name: _strdup. +#endif + +const int MIN_RUN_LENGTH = 3; +const int MAX_RUN_LENGTH = 127; + +// +// Compress an array of bytes, using run-length encoding, +// and return the length of the compressed data. +// + +static int rleCompress(int inLength, const char in[], signed char out[]) { + const char *inEnd = in + inLength; + const char *runStart = in; + const char *runEnd = in + 1; + signed char *outWrite = out; + + while (runStart < inEnd) { + while (runEnd < inEnd && *runStart == *runEnd && + runEnd - runStart - 1 < MAX_RUN_LENGTH) { + ++runEnd; + } + + if (runEnd - runStart >= MIN_RUN_LENGTH) { + // + // Compressible run + // + + *outWrite++ = static_cast<char>(runEnd - runStart) - 1; + *outWrite++ = *(reinterpret_cast<const signed char *>(runStart)); + runStart = runEnd; + } else { + // + // Uncompressable run + // + + while (runEnd < inEnd && + ((runEnd + 1 >= inEnd || *runEnd != *(runEnd + 1)) || + (runEnd + 2 >= inEnd || *(runEnd + 1) != *(runEnd + 2))) && + runEnd - runStart < MAX_RUN_LENGTH) { + ++runEnd; + } + + *outWrite++ = static_cast<char>(runStart - runEnd); + + while (runStart < runEnd) { + *outWrite++ = *(reinterpret_cast<const signed char *>(runStart++)); + } + } + + ++runEnd; + } + + return static_cast<int>(outWrite - out); +} + +// +// Uncompress an array of bytes compressed with rleCompress(). +// Returns the length of the uncompressed data, or 0 if the +// length of the uncompressed data would be more than maxLength. +// + +static int rleUncompress(int inLength, int maxLength, const signed char in[], + char out[]) { + char *outStart = out; + + while (inLength > 0) { + if (*in < 0) { + int count = -(static_cast<int>(*in++)); + inLength -= count + 1; + + // Fixes #116: Add bounds check to in buffer. + if ((0 > (maxLength -= count)) || (inLength < 0)) return 0; + + memcpy(out, in, count); + out += count; + in += count; + } else { + int count = *in++; + inLength -= 2; + + if ((0 > (maxLength -= count + 1)) || (inLength < 0)) return 0; + + memset(out, *reinterpret_cast<const char *>(in), count + 1); + out += count + 1; + + in++; + } + } + + return static_cast<int>(out - outStart); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// End of RLE code from OpenEXR ----------------------------------- + +static bool CompressRle(unsigned char *dst, + tinyexr::tinyexr_uint64 &compressedSize, + const unsigned char *src, unsigned long src_size) { + std::vector<unsigned char> tmpBuf(src_size); + + // + // Apply EXR-specific? postprocess. Grabbed from OpenEXR's + // ImfRleCompressor.cpp + // + + // + // Reorder the pixel data. + // + + const char *srcPtr = reinterpret_cast<const char *>(src); + + { + char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0)); + char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2; + const char *stop = srcPtr + src_size; + + for (;;) { + if (srcPtr < stop) + *(t1++) = *(srcPtr++); + else + break; + + if (srcPtr < stop) + *(t2++) = *(srcPtr++); + else + break; + } + } + + // + // Predictor. + // + + { + unsigned char *t = &tmpBuf.at(0) + 1; + unsigned char *stop = &tmpBuf.at(0) + src_size; + int p = t[-1]; + + while (t < stop) { + int d = int(t[0]) - p + (128 + 256); + p = t[0]; + t[0] = static_cast<unsigned char>(d); + ++t; + } + } + + // outSize will be (srcSiz * 3) / 2 at max. + int outSize = rleCompress(static_cast<int>(src_size), + reinterpret_cast<const char *>(&tmpBuf.at(0)), + reinterpret_cast<signed char *>(dst)); + TINYEXR_CHECK_AND_RETURN_C(outSize > 0, false); + + compressedSize = static_cast<tinyexr::tinyexr_uint64>(outSize); + + // Use uncompressed data when compressed data is larger than uncompressed. + // (Issue 40) + if (compressedSize >= src_size) { + compressedSize = src_size; + memcpy(dst, src, src_size); + } + + return true; +} + +static bool DecompressRle(unsigned char *dst, + const unsigned long uncompressed_size, + const unsigned char *src, unsigned long src_size) { + if (uncompressed_size == src_size) { + // Data is not compressed(Issue 40). + memcpy(dst, src, src_size); + return true; + } + + // Workaround for issue #112. + // TODO(syoyo): Add more robust out-of-bounds check in `rleUncompress`. + if (src_size <= 2) { + return false; + } + + std::vector<unsigned char> tmpBuf(uncompressed_size); + + int ret = rleUncompress(static_cast<int>(src_size), + static_cast<int>(uncompressed_size), + reinterpret_cast<const signed char *>(src), + reinterpret_cast<char *>(&tmpBuf.at(0))); + if (ret != static_cast<int>(uncompressed_size)) { + return false; + } + + // + // Apply EXR-specific? postprocess. Grabbed from OpenEXR's + // ImfRleCompressor.cpp + // + + // Predictor. + { + unsigned char *t = &tmpBuf.at(0) + 1; + unsigned char *stop = &tmpBuf.at(0) + uncompressed_size; + + while (t < stop) { + int d = int(t[-1]) + int(t[0]) - 128; + t[0] = static_cast<unsigned char>(d); + ++t; + } + } + + // Reorder the pixel data. + { + const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0)); + const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) + + (uncompressed_size + 1) / 2; + char *s = reinterpret_cast<char *>(dst); + char *stop = s + uncompressed_size; + + for (;;) { + if (s < stop) + *(s++) = *(t1++); + else + break; + + if (s < stop) + *(s++) = *(t2++); + else + break; + } + } + + return true; +} + +#if TINYEXR_USE_PIZ + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#pragma clang diagnostic ignored "-Wold-style-cast" +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wc++11-extensions" +#pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" + +#if __has_warning("-Wcast-qual") +#pragma clang diagnostic ignored "-Wcast-qual" +#endif + +#if __has_warning("-Wextra-semi-stmt") +#pragma clang diagnostic ignored "-Wextra-semi-stmt" +#endif + +#endif + +// +// PIZ compress/uncompress, based on OpenEXR's ImfPizCompressor.cpp +// +// ----------------------------------------------------------------- +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC) +// (3 clause BSD license) +// + +struct PIZChannelData { + unsigned short *start; + unsigned short *end; + int nx; + int ny; + int ys; + int size; +}; + +//----------------------------------------------------------------------------- +// +// 16-bit Haar Wavelet encoding and decoding +// +// The source code in this file is derived from the encoding +// and decoding routines written by Christian Rouet for his +// PIZ image file format. +// +//----------------------------------------------------------------------------- + +// +// Wavelet basis functions without modulo arithmetic; they produce +// the best compression ratios when the wavelet-transformed data are +// Huffman-encoded, but the wavelet transform works only for 14-bit +// data (untransformed data values must be less than (1 << 14)). +// + +inline void wenc14(unsigned short a, unsigned short b, unsigned short &l, + unsigned short &h) { + short as = static_cast<short>(a); + short bs = static_cast<short>(b); + + short ms = (as + bs) >> 1; + short ds = as - bs; + + l = static_cast<unsigned short>(ms); + h = static_cast<unsigned short>(ds); +} + +inline void wdec14(unsigned short l, unsigned short h, unsigned short &a, + unsigned short &b) { + short ls = static_cast<short>(l); + short hs = static_cast<short>(h); + + int hi = hs; + int ai = ls + (hi & 1) + (hi >> 1); + + short as = static_cast<short>(ai); + short bs = static_cast<short>(ai - hi); + + a = static_cast<unsigned short>(as); + b = static_cast<unsigned short>(bs); +} + +// +// Wavelet basis functions with modulo arithmetic; they work with full +// 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't +// compress the data quite as well. +// + +const int NBITS = 16; +const int A_OFFSET = 1 << (NBITS - 1); +const int M_OFFSET = 1 << (NBITS - 1); +const int MOD_MASK = (1 << NBITS) - 1; + +inline void wenc16(unsigned short a, unsigned short b, unsigned short &l, + unsigned short &h) { + int ao = (a + A_OFFSET) & MOD_MASK; + int m = ((ao + b) >> 1); + int d = ao - b; + + if (d < 0) m = (m + M_OFFSET) & MOD_MASK; + + d &= MOD_MASK; + + l = static_cast<unsigned short>(m); + h = static_cast<unsigned short>(d); +} + +inline void wdec16(unsigned short l, unsigned short h, unsigned short &a, + unsigned short &b) { + int m = l; + int d = h; + int bb = (m - (d >> 1)) & MOD_MASK; + int aa = (d + bb - A_OFFSET) & MOD_MASK; + b = static_cast<unsigned short>(bb); + a = static_cast<unsigned short>(aa); +} + +// +// 2D Wavelet encoding: +// + +static void wav2Encode( + unsigned short *in, // io: values are transformed in place + int nx, // i : x size + int ox, // i : x offset + int ny, // i : y size + int oy, // i : y offset + unsigned short mx) // i : maximum in[x][y] value +{ + bool w14 = (mx < (1 << 14)); + int n = (nx > ny) ? ny : nx; + int p = 1; // == 1 << level + int p2 = 2; // == 1 << (level+1) + + // + // Hierarchical loop on smaller dimension n + // + + while (p2 <= n) { + unsigned short *py = in; + unsigned short *ey = in + oy * (ny - p2); + int oy1 = oy * p; + int oy2 = oy * p2; + int ox1 = ox * p; + int ox2 = ox * p2; + unsigned short i00, i01, i10, i11; + + // + // Y loop + // + + for (; py <= ey; py += oy2) { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + // + // X loop + // + + for (; px <= ex; px += ox2) { + unsigned short *p01 = px + ox1; + unsigned short *p10 = px + oy1; + unsigned short *p11 = p10 + ox1; + + // + // 2D wavelet encoding + // + + if (w14) { + wenc14(*px, *p01, i00, i01); + wenc14(*p10, *p11, i10, i11); + wenc14(i00, i10, *px, *p10); + wenc14(i01, i11, *p01, *p11); + } else { + wenc16(*px, *p01, i00, i01); + wenc16(*p10, *p11, i10, i11); + wenc16(i00, i10, *px, *p10); + wenc16(i01, i11, *p01, *p11); + } + } + + // + // Encode (1D) odd column (still in Y loop) + // + + if (nx & p) { + unsigned short *p10 = px + oy1; + + if (w14) + wenc14(*px, *p10, i00, *p10); + else + wenc16(*px, *p10, i00, *p10); + + *px = i00; + } + } + + // + // Encode (1D) odd line (must loop in X) + // + + if (ny & p) { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + for (; px <= ex; px += ox2) { + unsigned short *p01 = px + ox1; + + if (w14) + wenc14(*px, *p01, i00, *p01); + else + wenc16(*px, *p01, i00, *p01); + + *px = i00; + } + } + + // + // Next level + // + + p = p2; + p2 <<= 1; + } +} + +// +// 2D Wavelet decoding: +// + +static void wav2Decode( + unsigned short *in, // io: values are transformed in place + int nx, // i : x size + int ox, // i : x offset + int ny, // i : y size + int oy, // i : y offset + unsigned short mx) // i : maximum in[x][y] value +{ + bool w14 = (mx < (1 << 14)); + int n = (nx > ny) ? ny : nx; + int p = 1; + int p2; + + // + // Search max level + // + + while (p <= n) p <<= 1; + + p >>= 1; + p2 = p; + p >>= 1; + + // + // Hierarchical loop on smaller dimension n + // + + while (p >= 1) { + unsigned short *py = in; + unsigned short *ey = in + oy * (ny - p2); + int oy1 = oy * p; + int oy2 = oy * p2; + int ox1 = ox * p; + int ox2 = ox * p2; + unsigned short i00, i01, i10, i11; + + // + // Y loop + // + + for (; py <= ey; py += oy2) { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + // + // X loop + // + + for (; px <= ex; px += ox2) { + unsigned short *p01 = px + ox1; + unsigned short *p10 = px + oy1; + unsigned short *p11 = p10 + ox1; + + // + // 2D wavelet decoding + // + + if (w14) { + wdec14(*px, *p10, i00, i10); + wdec14(*p01, *p11, i01, i11); + wdec14(i00, i01, *px, *p01); + wdec14(i10, i11, *p10, *p11); + } else { + wdec16(*px, *p10, i00, i10); + wdec16(*p01, *p11, i01, i11); + wdec16(i00, i01, *px, *p01); + wdec16(i10, i11, *p10, *p11); + } + } + + // + // Decode (1D) odd column (still in Y loop) + // + + if (nx & p) { + unsigned short *p10 = px + oy1; + + if (w14) + wdec14(*px, *p10, i00, *p10); + else + wdec16(*px, *p10, i00, *p10); + + *px = i00; + } + } + + // + // Decode (1D) odd line (must loop in X) + // + + if (ny & p) { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + for (; px <= ex; px += ox2) { + unsigned short *p01 = px + ox1; + + if (w14) + wdec14(*px, *p01, i00, *p01); + else + wdec16(*px, *p01, i00, *p01); + + *px = i00; + } + } + + // + // Next level + // + + p2 = p; + p >>= 1; + } +} + +//----------------------------------------------------------------------------- +// +// 16-bit Huffman compression and decompression. +// +// The source code in this file is derived from the 8-bit +// Huffman compression and decompression routines written +// by Christian Rouet for his PIZ image file format. +// +//----------------------------------------------------------------------------- + +// Adds some modification for tinyexr. + +const int HUF_ENCBITS = 16; // literal (value) bit length +const int HUF_DECBITS = 14; // decoding bit size (>= 8) + +const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1; // encoding table size +const int HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size +const int HUF_DECMASK = HUF_DECSIZE - 1; + +struct HufDec { // short code long code + //------------------------------- + unsigned int len : 8; // code length 0 + unsigned int lit : 24; // lit p size + unsigned int *p; // 0 lits +}; + +inline long long hufLength(long long code) { return code & 63; } + +inline long long hufCode(long long code) { return code >> 6; } + +inline void outputBits(int nBits, long long bits, long long &c, int &lc, + char *&out) { + c <<= nBits; + lc += nBits; + + c |= bits; + + while (lc >= 8) *out++ = static_cast<char>((c >> (lc -= 8))); +} + +inline long long getBits(int nBits, long long &c, int &lc, const char *&in) { + while (lc < nBits) { + c = (c << 8) | *(reinterpret_cast<const unsigned char *>(in++)); + lc += 8; + } + + lc -= nBits; + return (c >> lc) & ((1 << nBits) - 1); +} + +// +// ENCODING TABLE BUILDING & (UN)PACKING +// + +// +// Build a "canonical" Huffman code table: +// - for each (uncompressed) symbol, hcode contains the length +// of the corresponding code (in the compressed data) +// - canonical codes are computed and stored in hcode +// - the rules for constructing canonical codes are as follows: +// * shorter codes (if filled with zeroes to the right) +// have a numerically higher value than longer codes +// * for codes with the same length, numerical values +// increase with numerical symbol values +// - because the canonical code table can be constructed from +// symbol lengths alone, the code table can be transmitted +// without sending the actual code values +// - see http://www.compressconsult.com/huffman/ +// + +static void hufCanonicalCodeTable(long long hcode[HUF_ENCSIZE]) { + long long n[59]; + + // + // For each i from 0 through 58, count the + // number of different codes of length i, and + // store the count in n[i]. + // + + for (int i = 0; i <= 58; ++i) n[i] = 0; + + for (int i = 0; i < HUF_ENCSIZE; ++i) n[hcode[i]] += 1; + + // + // For each i from 58 through 1, compute the + // numerically lowest code with length i, and + // store that code in n[i]. + // + + long long c = 0; + + for (int i = 58; i > 0; --i) { + long long nc = ((c + n[i]) >> 1); + n[i] = c; + c = nc; + } + + // + // hcode[i] contains the length, l, of the + // code for symbol i. Assign the next available + // code of length l to the symbol and store both + // l and the code in hcode[i]. + // + + for (int i = 0; i < HUF_ENCSIZE; ++i) { + int l = static_cast<int>(hcode[i]); + + if (l > 0) hcode[i] = l | (n[l]++ << 6); + } +} + +// +// Compute Huffman codes (based on frq input) and store them in frq: +// - code structure is : [63:lsb - 6:msb] | [5-0: bit length]; +// - max code length is 58 bits; +// - codes outside the range [im-iM] have a null length (unused values); +// - original frequencies are destroyed; +// - encoding tables are used by hufEncode() and hufBuildDecTable(); +// + +struct FHeapCompare { + bool operator()(long long *a, long long *b) { return *a > *b; } +}; + +static bool hufBuildEncTable( + long long *frq, // io: input frequencies [HUF_ENCSIZE], output table + int *im, // o: min frq index + int *iM) // o: max frq index +{ + // + // This function assumes that when it is called, array frq + // indicates the frequency of all possible symbols in the data + // that are to be Huffman-encoded. (frq[i] contains the number + // of occurrences of symbol i in the data.) + // + // The loop below does three things: + // + // 1) Finds the minimum and maximum indices that point + // to non-zero entries in frq: + // + // frq[im] != 0, and frq[i] == 0 for all i < im + // frq[iM] != 0, and frq[i] == 0 for all i > iM + // + // 2) Fills array fHeap with pointers to all non-zero + // entries in frq. + // + // 3) Initializes array hlink such that hlink[i] == i + // for all array entries. + // + + std::vector<int> hlink(HUF_ENCSIZE); + std::vector<long long *> fHeap(HUF_ENCSIZE); + + *im = 0; + + while (!frq[*im]) (*im)++; + + int nf = 0; + + for (int i = *im; i < HUF_ENCSIZE; i++) { + hlink[i] = i; + + if (frq[i]) { + fHeap[nf] = &frq[i]; + nf++; + *iM = i; + } + } + + // + // Add a pseudo-symbol, with a frequency count of 1, to frq; + // adjust the fHeap and hlink array accordingly. Function + // hufEncode() uses the pseudo-symbol for run-length encoding. + // + + (*iM)++; + frq[*iM] = 1; + fHeap[nf] = &frq[*iM]; + nf++; + + // + // Build an array, scode, such that scode[i] contains the number + // of bits assigned to symbol i. Conceptually this is done by + // constructing a tree whose leaves are the symbols with non-zero + // frequency: + // + // Make a heap that contains all symbols with a non-zero frequency, + // with the least frequent symbol on top. + // + // Repeat until only one symbol is left on the heap: + // + // Take the two least frequent symbols off the top of the heap. + // Create a new node that has first two nodes as children, and + // whose frequency is the sum of the frequencies of the first + // two nodes. Put the new node back into the heap. + // + // The last node left on the heap is the root of the tree. For each + // leaf node, the distance between the root and the leaf is the length + // of the code for the corresponding symbol. + // + // The loop below doesn't actually build the tree; instead we compute + // the distances of the leaves from the root on the fly. When a new + // node is added to the heap, then that node's descendants are linked + // into a single linear list that starts at the new node, and the code + // lengths of the descendants (that is, their distance from the root + // of the tree) are incremented by one. + // + + std::make_heap(&fHeap[0], &fHeap[nf], FHeapCompare()); + + std::vector<long long> scode(HUF_ENCSIZE); + memset(scode.data(), 0, sizeof(long long) * HUF_ENCSIZE); + + while (nf > 1) { + // + // Find the indices, mm and m, of the two smallest non-zero frq + // values in fHeap, add the smallest frq to the second-smallest + // frq, and remove the smallest frq value from fHeap. + // + + int mm = fHeap[0] - frq; + std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare()); + --nf; + + int m = fHeap[0] - frq; + std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare()); + + frq[m] += frq[mm]; + std::push_heap(&fHeap[0], &fHeap[nf], FHeapCompare()); + + // + // The entries in scode are linked into lists with the + // entries in hlink serving as "next" pointers and with + // the end of a list marked by hlink[j] == j. + // + // Traverse the lists that start at scode[m] and scode[mm]. + // For each element visited, increment the length of the + // corresponding code by one bit. (If we visit scode[j] + // during the traversal, then the code for symbol j becomes + // one bit longer.) + // + // Merge the lists that start at scode[m] and scode[mm] + // into a single list that starts at scode[m]. + // + + // + // Add a bit to all codes in the first list. + // + + for (int j = m;; j = hlink[j]) { + scode[j]++; + + TINYEXR_CHECK_AND_RETURN_C(scode[j] <= 58, false); + + if (hlink[j] == j) { + // + // Merge the two lists. + // + + hlink[j] = mm; + break; + } + } + + // + // Add a bit to all codes in the second list + // + + for (int j = mm;; j = hlink[j]) { + scode[j]++; + + TINYEXR_CHECK_AND_RETURN_C(scode[j] <= 58, false); + + if (hlink[j] == j) break; + } + } + + // + // Build a canonical Huffman code table, replacing the code + // lengths in scode with (code, code length) pairs. Copy the + // code table from scode into frq. + // + + hufCanonicalCodeTable(scode.data()); + memcpy(frq, scode.data(), sizeof(long long) * HUF_ENCSIZE); + + return true; +} + +// +// Pack an encoding table: +// - only code lengths, not actual codes, are stored +// - runs of zeroes are compressed as follows: +// +// unpacked packed +// -------------------------------- +// 1 zero 0 (6 bits) +// 2 zeroes 59 +// 3 zeroes 60 +// 4 zeroes 61 +// 5 zeroes 62 +// n zeroes (6 or more) 63 n-6 (6 + 8 bits) +// + +const int SHORT_ZEROCODE_RUN = 59; +const int LONG_ZEROCODE_RUN = 63; +const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN; +const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN; + +static void hufPackEncTable( + const long long *hcode, // i : encoding table [HUF_ENCSIZE] + int im, // i : min hcode index + int iM, // i : max hcode index + char **pcode) // o: ptr to packed table (updated) +{ + char *p = *pcode; + long long c = 0; + int lc = 0; + + for (; im <= iM; im++) { + int l = hufLength(hcode[im]); + + if (l == 0) { + int zerun = 1; + + while ((im < iM) && (zerun < LONGEST_LONG_RUN)) { + if (hufLength(hcode[im + 1]) > 0) break; + im++; + zerun++; + } + + if (zerun >= 2) { + if (zerun >= SHORTEST_LONG_RUN) { + outputBits(6, LONG_ZEROCODE_RUN, c, lc, p); + outputBits(8, zerun - SHORTEST_LONG_RUN, c, lc, p); + } else { + outputBits(6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p); + } + continue; + } + } + + outputBits(6, l, c, lc, p); + } + + if (lc > 0) *p++ = (unsigned char)(c << (8 - lc)); + + *pcode = p; +} + +// +// Unpack an encoding table packed by hufPackEncTable(): +// + +static bool hufUnpackEncTable( + const char **pcode, // io: ptr to packed table (updated) + int ni, // i : input size (in bytes) + int im, // i : min hcode index + int iM, // i : max hcode index + long long *hcode) // o: encoding table [HUF_ENCSIZE] +{ + memset(hcode, 0, sizeof(long long) * HUF_ENCSIZE); + + const char *p = *pcode; + long long c = 0; + int lc = 0; + + for (; im <= iM; im++) { + if (p - *pcode >= ni) { + return false; + } + + long long l = hcode[im] = getBits(6, c, lc, p); // code length + + if (l == (long long)LONG_ZEROCODE_RUN) { + if (p - *pcode > ni) { + return false; + } + + int zerun = getBits(8, c, lc, p) + SHORTEST_LONG_RUN; + + if (im + zerun > iM + 1) { + return false; + } + + while (zerun--) hcode[im++] = 0; + + im--; + } else if (l >= (long long)SHORT_ZEROCODE_RUN) { + int zerun = l - SHORT_ZEROCODE_RUN + 2; + + if (im + zerun > iM + 1) { + return false; + } + + while (zerun--) hcode[im++] = 0; + + im--; + } + } + + *pcode = const_cast<char *>(p); + + hufCanonicalCodeTable(hcode); + + return true; +} + +// +// DECODING TABLE BUILDING +// + +// +// Clear a newly allocated decoding table so that it contains only zeroes. +// + +static void hufClearDecTable(HufDec *hdecod) // io: (allocated by caller) +// decoding table [HUF_DECSIZE] +{ + for (int i = 0; i < HUF_DECSIZE; i++) { + hdecod[i].len = 0; + hdecod[i].lit = 0; + hdecod[i].p = NULL; + } + // memset(hdecod, 0, sizeof(HufDec) * HUF_DECSIZE); +} + +// +// Build a decoding hash table based on the encoding table hcode: +// - short codes (<= HUF_DECBITS) are resolved with a single table access; +// - long code entry allocations are not optimized, because long codes are +// unfrequent; +// - decoding tables are used by hufDecode(); +// + +static bool hufBuildDecTable(const long long *hcode, // i : encoding table + int im, // i : min index in hcode + int iM, // i : max index in hcode + HufDec *hdecod) // o: (allocated by caller) +// decoding table [HUF_DECSIZE] +{ + // + // Init hashtable & loop on all codes. + // Assumes that hufClearDecTable(hdecod) has already been called. + // + + for (; im <= iM; im++) { + long long c = hufCode(hcode[im]); + int l = hufLength(hcode[im]); + + if (c >> l) { + // + // Error: c is supposed to be an l-bit code, + // but c contains a value that is greater + // than the largest l-bit number. + // + + // invalidTableEntry(); + return false; + } + + if (l > HUF_DECBITS) { + // + // Long code: add a secondary entry + // + + HufDec *pl = hdecod + (c >> (l - HUF_DECBITS)); + + if (pl->len) { + // + // Error: a short code has already + // been stored in table entry *pl. + // + + // invalidTableEntry(); + return false; + } + + pl->lit++; + + if (pl->p) { + unsigned int *p = pl->p; + pl->p = new unsigned int[pl->lit]; + + for (unsigned int i = 0; i < pl->lit - 1u; ++i) pl->p[i] = p[i]; + + delete[] p; + } else { + pl->p = new unsigned int[1]; + } + + pl->p[pl->lit - 1] = im; + } else if (l) { + // + // Short code: init all primary entries + // + + HufDec *pl = hdecod + (c << (HUF_DECBITS - l)); + + for (long long i = 1ULL << (HUF_DECBITS - l); i > 0; i--, pl++) { + if (pl->len || pl->p) { + // + // Error: a short code or a long code has + // already been stored in table entry *pl. + // + + // invalidTableEntry(); + return false; + } + + pl->len = l; + pl->lit = im; + } + } + } + + return true; +} + +// +// Free the long code entries of a decoding table built by hufBuildDecTable() +// + +static void hufFreeDecTable(HufDec *hdecod) // io: Decoding table +{ + for (int i = 0; i < HUF_DECSIZE; i++) { + if (hdecod[i].p) { + delete[] hdecod[i].p; + hdecod[i].p = 0; + } + } +} + +// +// ENCODING +// + +inline void outputCode(long long code, long long &c, int &lc, char *&out) { + outputBits(hufLength(code), hufCode(code), c, lc, out); +} + +inline void sendCode(long long sCode, int runCount, long long runCode, + long long &c, int &lc, char *&out) { + // + // Output a run of runCount instances of the symbol sCount. + // Output the symbols explicitly, or if that is shorter, output + // the sCode symbol once followed by a runCode symbol and runCount + // expressed as an 8-bit number. + // + + if (hufLength(sCode) + hufLength(runCode) + 8 < hufLength(sCode) * runCount) { + outputCode(sCode, c, lc, out); + outputCode(runCode, c, lc, out); + outputBits(8, runCount, c, lc, out); + } else { + while (runCount-- >= 0) outputCode(sCode, c, lc, out); + } +} + +// +// Encode (compress) ni values based on the Huffman encoding table hcode: +// + +static int hufEncode // return: output size (in bits) + (const long long *hcode, // i : encoding table + const unsigned short *in, // i : uncompressed input buffer + const int ni, // i : input buffer size (in bytes) + int rlc, // i : rl code + char *out) // o: compressed output buffer +{ + char *outStart = out; + long long c = 0; // bits not yet written to out + int lc = 0; // number of valid bits in c (LSB) + int s = in[0]; + int cs = 0; + + // + // Loop on input values + // + + for (int i = 1; i < ni; i++) { + // + // Count same values or send code + // + + if (s == in[i] && cs < 255) { + cs++; + } else { + sendCode(hcode[s], cs, hcode[rlc], c, lc, out); + cs = 0; + } + + s = in[i]; + } + + // + // Send remaining code + // + + sendCode(hcode[s], cs, hcode[rlc], c, lc, out); + + if (lc) *out = (c << (8 - lc)) & 0xff; + + return (out - outStart) * 8 + lc; +} + +// +// DECODING +// + +// +// In order to force the compiler to inline them, +// getChar() and getCode() are implemented as macros +// instead of "inline" functions. +// + +#define getChar(c, lc, in) \ + { \ + c = (c << 8) | *(unsigned char *)(in++); \ + lc += 8; \ + } + +#if 0 +#define getCode(po, rlc, c, lc, in, out, ob, oe) \ + { \ + if (po == rlc) { \ + if (lc < 8) getChar(c, lc, in); \ + \ + lc -= 8; \ + \ + unsigned char cs = (c >> lc); \ + \ + if (out + cs > oe) return false; \ + \ + /* TinyEXR issue 78 */ \ + unsigned short s = out[-1]; \ + \ + while (cs-- > 0) *out++ = s; \ + } else if (out < oe) { \ + *out++ = po; \ + } else { \ + return false; \ + } \ + } +#else +static bool getCode(int po, int rlc, long long &c, int &lc, const char *&in, + const char *in_end, unsigned short *&out, + const unsigned short *ob, const unsigned short *oe) { + (void)ob; + if (po == rlc) { + if (lc < 8) { + /* TinyEXR issue 78 */ + /* TinyEXR issue 160. in + 1 -> in */ + if (in >= in_end) { + return false; + } + + getChar(c, lc, in); + } + + lc -= 8; + + unsigned char cs = (c >> lc); + + if (out + cs > oe) return false; + + // Bounds check for safety + // Issue 100. + if ((out - 1) < ob) return false; + unsigned short s = out[-1]; + + while (cs-- > 0) *out++ = s; + } else if (out < oe) { + *out++ = po; + } else { + return false; + } + return true; +} +#endif + +// +// Decode (uncompress) ni bits based on encoding & decoding tables: +// + +static bool hufDecode(const long long *hcode, // i : encoding table + const HufDec *hdecod, // i : decoding table + const char *in, // i : compressed input buffer + int ni, // i : input size (in bits) + int rlc, // i : run-length code + int no, // i : expected output size (in bytes) + unsigned short *out) // o: uncompressed output buffer +{ + long long c = 0; + int lc = 0; + unsigned short *outb = out; // begin + unsigned short *oe = out + no; // end + const char *ie = in + (ni + 7) / 8; // input byte size + + // + // Loop on input bytes + // + + while (in < ie) { + getChar(c, lc, in); + + // + // Access decoding table + // + + while (lc >= HUF_DECBITS) { + const HufDec pl = hdecod[(c >> (lc - HUF_DECBITS)) & HUF_DECMASK]; + + if (pl.len) { + // + // Get short code + // + + lc -= pl.len; + // std::cout << "lit = " << pl.lit << std::endl; + // std::cout << "rlc = " << rlc << std::endl; + // std::cout << "c = " << c << std::endl; + // std::cout << "lc = " << lc << std::endl; + // std::cout << "in = " << in << std::endl; + // std::cout << "out = " << out << std::endl; + // std::cout << "oe = " << oe << std::endl; + if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) { + return false; + } + } else { + if (!pl.p) { + return false; + } + // invalidCode(); // wrong code + + // + // Search long code + // + + unsigned int j; + + for (j = 0; j < pl.lit; j++) { + int l = hufLength(hcode[pl.p[j]]); + + while (lc < l && in < ie) // get more bits + getChar(c, lc, in); + + if (lc >= l) { + if (hufCode(hcode[pl.p[j]]) == + ((c >> (lc - l)) & (((long long)(1) << l) - 1))) { + // + // Found : get long code + // + + lc -= l; + if (!getCode(pl.p[j], rlc, c, lc, in, ie, out, outb, oe)) { + return false; + } + break; + } + } + } + + if (j == pl.lit) { + return false; + // invalidCode(); // Not found + } + } + } + } + + // + // Get remaining (short) codes + // + + int i = (8 - ni) & 7; + c >>= i; + lc -= i; + + while (lc > 0) { + const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK]; + + if (pl.len) { + lc -= pl.len; + if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) { + return false; + } + } else { + return false; + // invalidCode(); // wrong (long) code + } + } + + if (out - outb != no) { + return false; + } + // notEnoughData (); + + return true; +} + +static void countFrequencies(std::vector<long long> &freq, + const unsigned short data[/*n*/], int n) { + for (int i = 0; i < HUF_ENCSIZE; ++i) freq[i] = 0; + + for (int i = 0; i < n; ++i) ++freq[data[i]]; +} + +static void writeUInt(char buf[4], unsigned int i) { + unsigned char *b = (unsigned char *)buf; + + b[0] = i; + b[1] = i >> 8; + b[2] = i >> 16; + b[3] = i >> 24; +} + +static unsigned int readUInt(const char buf[4]) { + const unsigned char *b = (const unsigned char *)buf; + + return (b[0] & 0x000000ff) | ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | ((b[3] << 24) & 0xff000000); +} + +// +// EXTERNAL INTERFACE +// + +static int hufCompress(const unsigned short raw[], int nRaw, + char compressed[]) { + if (nRaw == 0) return 0; + + std::vector<long long> freq(HUF_ENCSIZE); + + countFrequencies(freq, raw, nRaw); + + int im = 0; + int iM = 0; + hufBuildEncTable(freq.data(), &im, &iM); + + char *tableStart = compressed + 20; + char *tableEnd = tableStart; + hufPackEncTable(freq.data(), im, iM, &tableEnd); + int tableLength = tableEnd - tableStart; + + char *dataStart = tableEnd; + int nBits = hufEncode(freq.data(), raw, nRaw, iM, dataStart); + int data_length = (nBits + 7) / 8; + + writeUInt(compressed, im); + writeUInt(compressed + 4, iM); + writeUInt(compressed + 8, tableLength); + writeUInt(compressed + 12, nBits); + writeUInt(compressed + 16, 0); // room for future extensions + + return dataStart + data_length - compressed; +} + +static bool hufUncompress(const char compressed[], int nCompressed, + std::vector<unsigned short> *raw) { + if (nCompressed == 0) { + if (raw->size() != 0) return false; + + return false; + } + + int im = readUInt(compressed); + int iM = readUInt(compressed + 4); + // int tableLength = readUInt (compressed + 8); + int nBits = readUInt(compressed + 12); + + if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) return false; + + const char *ptr = compressed + 20; + + // + // Fast decoder needs at least 2x64-bits of compressed data, and + // needs to be run-able on this platform. Otherwise, fall back + // to the original decoder + // + + // if (FastHufDecoder::enabled() && nBits > 128) + //{ + // FastHufDecoder fhd (ptr, nCompressed - (ptr - compressed), im, iM, iM); + // fhd.decode ((unsigned char*)ptr, nBits, raw, nRaw); + //} + // else + { + std::vector<long long> freq(HUF_ENCSIZE); + std::vector<HufDec> hdec(HUF_DECSIZE); + + hufClearDecTable(&hdec.at(0)); + + hufUnpackEncTable(&ptr, nCompressed - (ptr - compressed), im, iM, + &freq.at(0)); + + { + if (nBits > 8 * (nCompressed - (ptr - compressed))) { + return false; + } + + hufBuildDecTable(&freq.at(0), im, iM, &hdec.at(0)); + hufDecode(&freq.at(0), &hdec.at(0), ptr, nBits, iM, raw->size(), + raw->data()); + } + // catch (...) + //{ + // hufFreeDecTable (hdec); + // throw; + //} + + hufFreeDecTable(&hdec.at(0)); + } + + return true; +} + +// +// Functions to compress the range of values in the pixel data +// + +const int USHORT_RANGE = (1 << 16); +const int BITMAP_SIZE = (USHORT_RANGE >> 3); + +static void bitmapFromData(const unsigned short data[/*nData*/], int nData, + unsigned char bitmap[BITMAP_SIZE], + unsigned short &minNonZero, + unsigned short &maxNonZero) { + for (int i = 0; i < BITMAP_SIZE; ++i) bitmap[i] = 0; + + for (int i = 0; i < nData; ++i) bitmap[data[i] >> 3] |= (1 << (data[i] & 7)); + + bitmap[0] &= ~1; // zero is not explicitly stored in + // the bitmap; we assume that the + // data always contain zeroes + minNonZero = BITMAP_SIZE - 1; + maxNonZero = 0; + + for (int i = 0; i < BITMAP_SIZE; ++i) { + if (bitmap[i]) { + if (minNonZero > i) minNonZero = i; + if (maxNonZero < i) maxNonZero = i; + } + } +} + +static unsigned short forwardLutFromBitmap( + const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) { + int k = 0; + + for (int i = 0; i < USHORT_RANGE; ++i) { + if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) + lut[i] = k++; + else + lut[i] = 0; + } + + return k - 1; // maximum value stored in lut[], +} // i.e. number of ones in bitmap minus 1 + +static unsigned short reverseLutFromBitmap( + const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) { + int k = 0; + + for (int i = 0; i < USHORT_RANGE; ++i) { + if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) lut[k++] = i; + } + + int n = k - 1; + + while (k < USHORT_RANGE) lut[k++] = 0; + + return n; // maximum k where lut[k] is non-zero, +} // i.e. number of ones in bitmap minus 1 + +static void applyLut(const unsigned short lut[USHORT_RANGE], + unsigned short data[/*nData*/], int nData) { + for (int i = 0; i < nData; ++i) data[i] = lut[data[i]]; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif // __clang__ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize, + const unsigned char *inPtr, size_t inSize, + const std::vector<ChannelInfo> &channelInfo, + int data_width, int num_lines) { + std::vector<unsigned char> bitmap(BITMAP_SIZE); + unsigned short minNonZero; + unsigned short maxNonZero; + +#if !TINYEXR_LITTLE_ENDIAN + // @todo { PIZ compression on BigEndian architecture. } + return false; +#endif + + // Assume `inSize` is multiple of 2 or 4. + std::vector<unsigned short> tmpBuffer(inSize / sizeof(unsigned short)); + + std::vector<PIZChannelData> channelData(channelInfo.size()); + unsigned short *tmpBufferEnd = &tmpBuffer.at(0); + + for (size_t c = 0; c < channelData.size(); c++) { + PIZChannelData &cd = channelData[c]; + + cd.start = tmpBufferEnd; + cd.end = cd.start; + + cd.nx = data_width; + cd.ny = num_lines; + // cd.ys = c.channel().ySampling; + + size_t pixelSize = sizeof(int); // UINT and FLOAT + if (channelInfo[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) { + pixelSize = sizeof(short); + } + + cd.size = static_cast<int>(pixelSize / sizeof(short)); + + tmpBufferEnd += cd.nx * cd.ny * cd.size; + } + + const unsigned char *ptr = inPtr; + for (int y = 0; y < num_lines; ++y) { + for (size_t i = 0; i < channelData.size(); ++i) { + PIZChannelData &cd = channelData[i]; + + // if (modp (y, cd.ys) != 0) + // continue; + + size_t n = static_cast<size_t>(cd.nx * cd.size); + memcpy(cd.end, ptr, n * sizeof(unsigned short)); + ptr += n * sizeof(unsigned short); + cd.end += n; + } + } + + bitmapFromData(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), + bitmap.data(), minNonZero, maxNonZero); + + std::vector<unsigned short> lut(USHORT_RANGE); + unsigned short maxValue = forwardLutFromBitmap(bitmap.data(), lut.data()); + applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBuffer.size())); + + // + // Store range compression info in _outBuffer + // + + char *buf = reinterpret_cast<char *>(outPtr); + + memcpy(buf, &minNonZero, sizeof(unsigned short)); + buf += sizeof(unsigned short); + memcpy(buf, &maxNonZero, sizeof(unsigned short)); + buf += sizeof(unsigned short); + + if (minNonZero <= maxNonZero) { + memcpy(buf, reinterpret_cast<char *>(&bitmap[0] + minNonZero), + maxNonZero - minNonZero + 1); + buf += maxNonZero - minNonZero + 1; + } + + // + // Apply wavelet encoding + // + + for (size_t i = 0; i < channelData.size(); ++i) { + PIZChannelData &cd = channelData[i]; + + for (int j = 0; j < cd.size; ++j) { + wav2Encode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size, + maxValue); + } + } + + // + // Apply Huffman encoding; append the result to _outBuffer + // + + // length header(4byte), then huff data. Initialize length header with zero, + // then later fill it by `length`. + char *lengthPtr = buf; + int zero = 0; + memcpy(buf, &zero, sizeof(int)); + buf += sizeof(int); + + int length = + hufCompress(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), buf); + memcpy(lengthPtr, &length, sizeof(int)); + + (*outSize) = static_cast<unsigned int>( + (reinterpret_cast<unsigned char *>(buf) - outPtr) + + static_cast<unsigned int>(length)); + + // Use uncompressed data when compressed data is larger than uncompressed. + // (Issue 40) + if ((*outSize) >= inSize) { + (*outSize) = static_cast<unsigned int>(inSize); + memcpy(outPtr, inPtr, inSize); + } + return true; +} + +static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, + size_t tmpBufSizeInBytes, size_t inLen, int num_channels, + const EXRChannelInfo *channels, int data_width, + int num_lines) { + if (inLen == tmpBufSizeInBytes) { + // Data is not compressed(Issue 40). + memcpy(outPtr, inPtr, inLen); + return true; + } + + std::vector<unsigned char> bitmap(BITMAP_SIZE); + unsigned short minNonZero; + unsigned short maxNonZero; + +#if !TINYEXR_LITTLE_ENDIAN + // @todo { PIZ compression on BigEndian architecture. } + return false; +#endif + + memset(bitmap.data(), 0, BITMAP_SIZE); + + if (inLen < 4) { + return false; + } + + size_t readLen = 0; + + const unsigned char *ptr = inPtr; + // minNonZero = *(reinterpret_cast<const unsigned short *>(ptr)); + tinyexr::cpy2(&minNonZero, reinterpret_cast<const unsigned short *>(ptr)); + // maxNonZero = *(reinterpret_cast<const unsigned short *>(ptr + 2)); + tinyexr::cpy2(&maxNonZero, reinterpret_cast<const unsigned short *>(ptr + 2)); + ptr += 4; + readLen += 4; + + if (maxNonZero >= BITMAP_SIZE) { + return false; + } + + //printf("maxNonZero = %d\n", maxNonZero); + //printf("minNonZero = %d\n", minNonZero); + //printf("len = %d\n", (maxNonZero - minNonZero + 1)); + //printf("BITMAPSIZE - min = %d\n", (BITMAP_SIZE - minNonZero)); + + if (minNonZero <= maxNonZero) { + if (((maxNonZero - minNonZero + 1) + readLen) > inLen) { + // Input too short + return false; + } + + memcpy(reinterpret_cast<char *>(&bitmap[0] + minNonZero), ptr, + maxNonZero - minNonZero + 1); + ptr += maxNonZero - minNonZero + 1; + readLen += maxNonZero - minNonZero + 1; + } else { + // Issue 194 + if ((minNonZero == (BITMAP_SIZE - 1)) && (maxNonZero == 0)) { + // OK. all pixels are zero. And no need to read `bitmap` data. + } else { + // invalid minNonZero/maxNonZero combination. + return false; + } + } + + std::vector<unsigned short> lut(USHORT_RANGE); + memset(lut.data(), 0, sizeof(unsigned short) * USHORT_RANGE); + unsigned short maxValue = reverseLutFromBitmap(bitmap.data(), lut.data()); + + // + // Huffman decoding + // + + if ((readLen + 4) > inLen) { + return false; + } + + int length=0; + + // length = *(reinterpret_cast<const int *>(ptr)); + tinyexr::cpy4(&length, reinterpret_cast<const int *>(ptr)); + ptr += sizeof(int); + + if (size_t((ptr - inPtr) + length) > inLen) { + return false; + } + + std::vector<unsigned short> tmpBuffer(tmpBufSizeInBytes / sizeof(unsigned short)); + hufUncompress(reinterpret_cast<const char *>(ptr), length, &tmpBuffer); + + // + // Wavelet decoding + // + + std::vector<PIZChannelData> channelData(static_cast<size_t>(num_channels)); + + unsigned short *tmpBufferEnd = &tmpBuffer.at(0); + + for (size_t i = 0; i < static_cast<size_t>(num_channels); ++i) { + const EXRChannelInfo &chan = channels[i]; + + size_t pixelSize = sizeof(int); // UINT and FLOAT + if (chan.pixel_type == TINYEXR_PIXELTYPE_HALF) { + pixelSize = sizeof(short); + } + + channelData[i].start = tmpBufferEnd; + channelData[i].end = channelData[i].start; + channelData[i].nx = data_width; + channelData[i].ny = num_lines; + // channelData[i].ys = 1; + channelData[i].size = static_cast<int>(pixelSize / sizeof(short)); + + tmpBufferEnd += channelData[i].nx * channelData[i].ny * channelData[i].size; + } + + for (size_t i = 0; i < channelData.size(); ++i) { + PIZChannelData &cd = channelData[i]; + + for (int j = 0; j < cd.size; ++j) { + wav2Decode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size, + maxValue); + } + } + + // + // Expand the pixel data to their original range + // + + applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBufSizeInBytes / sizeof(unsigned short))); + + for (int y = 0; y < num_lines; y++) { + for (size_t i = 0; i < channelData.size(); ++i) { + PIZChannelData &cd = channelData[i]; + + // if (modp (y, cd.ys) != 0) + // continue; + + size_t n = static_cast<size_t>(cd.nx * cd.size); + memcpy(outPtr, cd.end, static_cast<size_t>(n * sizeof(unsigned short))); + outPtr += n * sizeof(unsigned short); + cd.end += n; + } + } + + return true; +} +#endif // TINYEXR_USE_PIZ + +#if TINYEXR_USE_ZFP + +struct ZFPCompressionParam { + double rate; + unsigned int precision; + unsigned int __pad0; + double tolerance; + int type; // TINYEXR_ZFP_COMPRESSIONTYPE_* + unsigned int __pad1; + + ZFPCompressionParam() { + type = TINYEXR_ZFP_COMPRESSIONTYPE_RATE; + rate = 2.0; + precision = 0; + tolerance = 0.0; + } +}; + +static bool FindZFPCompressionParam(ZFPCompressionParam *param, + const EXRAttribute *attributes, + int num_attributes, std::string *err) { + bool foundType = false; + + for (int i = 0; i < num_attributes; i++) { + if ((strcmp(attributes[i].name, "zfpCompressionType") == 0)) { + if (attributes[i].size == 1) { + param->type = static_cast<int>(attributes[i].value[0]); + foundType = true; + break; + } else { + if (err) { + (*err) += + "zfpCompressionType attribute must be uchar(1 byte) type.\n"; + } + return false; + } + } + } + + if (!foundType) { + if (err) { + (*err) += "`zfpCompressionType` attribute not found.\n"; + } + return false; + } + + if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) { + for (int i = 0; i < num_attributes; i++) { + if ((strcmp(attributes[i].name, "zfpCompressionRate") == 0) && + (attributes[i].size == 8)) { + param->rate = *(reinterpret_cast<double *>(attributes[i].value)); + return true; + } + } + + if (err) { + (*err) += "`zfpCompressionRate` attribute not found.\n"; + } + + } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) { + for (int i = 0; i < num_attributes; i++) { + if ((strcmp(attributes[i].name, "zfpCompressionPrecision") == 0) && + (attributes[i].size == 4)) { + param->rate = *(reinterpret_cast<int *>(attributes[i].value)); + return true; + } + } + + if (err) { + (*err) += "`zfpCompressionPrecision` attribute not found.\n"; + } + + } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) { + for (int i = 0; i < num_attributes; i++) { + if ((strcmp(attributes[i].name, "zfpCompressionTolerance") == 0) && + (attributes[i].size == 8)) { + param->tolerance = *(reinterpret_cast<double *>(attributes[i].value)); + return true; + } + } + + if (err) { + (*err) += "`zfpCompressionTolerance` attribute not found.\n"; + } + } else { + if (err) { + (*err) += "Unknown value specified for `zfpCompressionType`.\n"; + } + } + + return false; +} + +// Assume pixel format is FLOAT for all channels. +static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines, + size_t num_channels, const unsigned char *src, + unsigned long src_size, + const ZFPCompressionParam ¶m) { + size_t uncompressed_size = + size_t(dst_width) * size_t(dst_num_lines) * num_channels; + + if (uncompressed_size == src_size) { + // Data is not compressed(Issue 40). + memcpy(dst, src, src_size); + } + + zfp_stream *zfp = NULL; + zfp_field *field = NULL; + + TINYEXR_CHECK_AND_RETURN_C((dst_width % 4) == 0, false); + TINYEXR_CHECK_AND_RETURN_C((dst_num_lines % 4) == 0, false); + + if ((size_t(dst_width) & 3U) || (size_t(dst_num_lines) & 3U)) { + return false; + } + + field = + zfp_field_2d(reinterpret_cast<void *>(const_cast<unsigned char *>(src)), + zfp_type_float, static_cast<unsigned int>(dst_width), + static_cast<unsigned int>(dst_num_lines) * + static_cast<unsigned int>(num_channels)); + zfp = zfp_stream_open(NULL); + + if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) { + zfp_stream_set_rate(zfp, param.rate, zfp_type_float, /* dimension */ 2, + /* write random access */ 0); + } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) { + zfp_stream_set_precision(zfp, param.precision); + } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) { + zfp_stream_set_accuracy(zfp, param.tolerance); + } else { + return false; + } + + size_t buf_size = zfp_stream_maximum_size(zfp, field); + std::vector<unsigned char> buf(buf_size); + memcpy(&buf.at(0), src, src_size); + + bitstream *stream = stream_open(&buf.at(0), buf_size); + zfp_stream_set_bit_stream(zfp, stream); + zfp_stream_rewind(zfp); + + size_t image_size = size_t(dst_width) * size_t(dst_num_lines); + + for (size_t c = 0; c < size_t(num_channels); c++) { + // decompress 4x4 pixel block. + for (size_t y = 0; y < size_t(dst_num_lines); y += 4) { + for (size_t x = 0; x < size_t(dst_width); x += 4) { + float fblock[16]; + zfp_decode_block_float_2(zfp, fblock); + for (size_t j = 0; j < 4; j++) { + for (size_t i = 0; i < 4; i++) { + dst[c * image_size + ((y + j) * size_t(dst_width) + (x + i))] = + fblock[j * 4 + i]; + } + } + } + } + } + + zfp_field_free(field); + zfp_stream_close(zfp); + stream_close(stream); + + return true; +} + +// Assume pixel format is FLOAT for all channels. +static bool CompressZfp(std::vector<unsigned char> *outBuf, + unsigned int *outSize, const float *inPtr, int width, + int num_lines, int num_channels, + const ZFPCompressionParam ¶m) { + zfp_stream *zfp = NULL; + zfp_field *field = NULL; + + TINYEXR_CHECK_AND_RETURN_C((width % 4) == 0, false); + TINYEXR_CHECK_AND_RETURN_C((num_lines % 4) == 0, false); + + if ((size_t(width) & 3U) || (size_t(num_lines) & 3U)) { + return false; + } + + // create input array. + field = zfp_field_2d(reinterpret_cast<void *>(const_cast<float *>(inPtr)), + zfp_type_float, static_cast<unsigned int>(width), + static_cast<unsigned int>(num_lines * num_channels)); + + zfp = zfp_stream_open(NULL); + + if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) { + zfp_stream_set_rate(zfp, param.rate, zfp_type_float, 2, 0); + } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) { + zfp_stream_set_precision(zfp, param.precision); + } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) { + zfp_stream_set_accuracy(zfp, param.tolerance); + } else { + return false; + } + + size_t buf_size = zfp_stream_maximum_size(zfp, field); + + outBuf->resize(buf_size); + + bitstream *stream = stream_open(&outBuf->at(0), buf_size); + zfp_stream_set_bit_stream(zfp, stream); + zfp_field_free(field); + + size_t image_size = size_t(width) * size_t(num_lines); + + for (size_t c = 0; c < size_t(num_channels); c++) { + // compress 4x4 pixel block. + for (size_t y = 0; y < size_t(num_lines); y += 4) { + for (size_t x = 0; x < size_t(width); x += 4) { + float fblock[16]; + for (size_t j = 0; j < 4; j++) { + for (size_t i = 0; i < 4; i++) { + fblock[j * 4 + i] = + inPtr[c * image_size + ((y + j) * size_t(width) + (x + i))]; + } + } + zfp_encode_block_float_2(zfp, fblock); + } + } + } + + zfp_stream_flush(zfp); + (*outSize) = static_cast<unsigned int>(zfp_stream_compressed_size(zfp)); + + zfp_stream_close(zfp); + + return true; +} + +#endif + +// +// ----------------------------------------------------------------- +// + +// heuristics +#define TINYEXR_DIMENSION_THRESHOLD (1024 * 8192) + +// TODO(syoyo): Refactor function arguments. +static bool DecodePixelData(/* out */ unsigned char **out_images, + const int *requested_pixel_types, + const unsigned char *data_ptr, size_t data_len, + int compression_type, int line_order, int width, + int height, int x_stride, int y, int line_no, + int num_lines, size_t pixel_data_size, + size_t num_attributes, + const EXRAttribute *attributes, size_t num_channels, + const EXRChannelInfo *channels, + const std::vector<size_t> &channel_offset_list) { + if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { // PIZ +#if TINYEXR_USE_PIZ + if ((width == 0) || (num_lines == 0) || (pixel_data_size == 0)) { + // Invalid input #90 + return false; + } + + // Allocate original data size. + std::vector<unsigned char> outBuf(static_cast<size_t>( + static_cast<size_t>(width * num_lines) * pixel_data_size)); + size_t tmpBufLen = outBuf.size(); + + bool ret = tinyexr::DecompressPiz( + reinterpret_cast<unsigned char *>(&outBuf.at(0)), data_ptr, tmpBufLen, + data_len, static_cast<int>(num_channels), channels, width, num_lines); + + if (!ret) { + return false; + } + + // For PIZ_COMPRESSION: + // pixel sample data for channel 0 for scanline 0 + // pixel sample data for channel 1 for scanline 0 + // pixel sample data for channel ... for scanline 0 + // pixel sample data for channel n for scanline 0 + // pixel sample data for channel 0 for scanline 1 + // pixel sample data for channel 1 for scanline 1 + // pixel sample data for channel ... for scanline 1 + // pixel sample data for channel n for scanline 1 + // ... + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + FP16 hf; + + // hf.u = line_ptr[u]; + // use `cpy` to avoid unaligned memory access when compiler's + // optimization is on. + tinyexr::cpy2(&(hf.u), line_ptr + u); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { + unsigned short *image = + reinterpret_cast<unsigned short **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += static_cast<size_t>( + (height - 1 - (line_no + static_cast<int>(v)))) * + static_cast<size_t>(x_stride) + + u; + } + *image = hf.u; + } else { // HALF -> FLOAT + FP32 f32 = half_to_float(hf); + float *image = reinterpret_cast<float **>(out_images)[c]; + size_t offset = 0; + if (line_order == 0) { + offset = (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + offset = static_cast<size_t>( + (height - 1 - (line_no + static_cast<int>(v)))) * + static_cast<size_t>(x_stride) + + u; + } + image += offset; + *image = f32.f; + } + } + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT, false); + + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const unsigned int *line_ptr = reinterpret_cast<unsigned int *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + unsigned int val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(&val); + + unsigned int *image = + reinterpret_cast<unsigned int **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += static_cast<size_t>( + (height - 1 - (line_no + static_cast<int>(v)))) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false); + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const float *line_ptr = reinterpret_cast<float *>(&outBuf.at( + v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + float val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + + float *image = reinterpret_cast<float **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += static_cast<size_t>( + (height - 1 - (line_no + static_cast<int>(v)))) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else { + return false; + } + } +#else + return false; +#endif + + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS || + compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) { + // Allocate original data size. + std::vector<unsigned char> outBuf(static_cast<size_t>(width) * + static_cast<size_t>(num_lines) * + pixel_data_size); + + unsigned long dstLen = static_cast<unsigned long>(outBuf.size()); + TINYEXR_CHECK_AND_RETURN_C(dstLen > 0, false); + if (!tinyexr::DecompressZip( + reinterpret_cast<unsigned char *>(&outBuf.at(0)), &dstLen, data_ptr, + static_cast<unsigned long>(data_len))) { + return false; + } + + // For ZIP_COMPRESSION: + // pixel sample data for channel 0 for scanline 0 + // pixel sample data for channel 1 for scanline 0 + // pixel sample data for channel ... for scanline 0 + // pixel sample data for channel n for scanline 0 + // pixel sample data for channel 0 for scanline 1 + // pixel sample data for channel 1 for scanline 1 + // pixel sample data for channel ... for scanline 1 + // pixel sample data for channel n for scanline 1 + // ... + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &outBuf.at(v * static_cast<size_t>(pixel_data_size) * + static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + tinyexr::FP16 hf; + + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { + unsigned short *image = + reinterpret_cast<unsigned short **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = hf.u; + } else { // HALF -> FLOAT + tinyexr::FP32 f32 = half_to_float(hf); + float *image = reinterpret_cast<float **>(out_images)[c]; + size_t offset = 0; + if (line_order == 0) { + offset = (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + offset = (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + image += offset; + + *image = f32.f; + } + } + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT, false); + + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const unsigned int *line_ptr = reinterpret_cast<unsigned int *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + unsigned int val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(&val); + + unsigned int *image = + reinterpret_cast<unsigned int **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false); + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const float *line_ptr = reinterpret_cast<float *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + float val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + + float *image = reinterpret_cast<float **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else { + return false; + } + } + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) { + // Allocate original data size. + std::vector<unsigned char> outBuf(static_cast<size_t>(width) * + static_cast<size_t>(num_lines) * + pixel_data_size); + + unsigned long dstLen = static_cast<unsigned long>(outBuf.size()); + if (dstLen == 0) { + return false; + } + + if (!tinyexr::DecompressRle( + reinterpret_cast<unsigned char *>(&outBuf.at(0)), dstLen, data_ptr, + static_cast<unsigned long>(data_len))) { + return false; + } + + // For RLE_COMPRESSION: + // pixel sample data for channel 0 for scanline 0 + // pixel sample data for channel 1 for scanline 0 + // pixel sample data for channel ... for scanline 0 + // pixel sample data for channel n for scanline 0 + // pixel sample data for channel 0 for scanline 1 + // pixel sample data for channel 1 for scanline 1 + // pixel sample data for channel ... for scanline 1 + // pixel sample data for channel n for scanline 1 + // ... + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &outBuf.at(v * static_cast<size_t>(pixel_data_size) * + static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + tinyexr::FP16 hf; + + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { + unsigned short *image = + reinterpret_cast<unsigned short **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = hf.u; + } else { // HALF -> FLOAT + tinyexr::FP32 f32 = half_to_float(hf); + float *image = reinterpret_cast<float **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = f32.f; + } + } + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT, false); + + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const unsigned int *line_ptr = reinterpret_cast<unsigned int *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + unsigned int val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(&val); + + unsigned int *image = + reinterpret_cast<unsigned int **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false); + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const float *line_ptr = reinterpret_cast<float *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + float val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + + float *image = reinterpret_cast<float **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else { + return false; + } + } + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { +#if TINYEXR_USE_ZFP + tinyexr::ZFPCompressionParam zfp_compression_param; + std::string e; + if (!tinyexr::FindZFPCompressionParam(&zfp_compression_param, attributes, + int(num_attributes), &e)) { + // This code path should not be reachable. + return false; + } + + // Allocate original data size. + std::vector<unsigned char> outBuf(static_cast<size_t>(width) * + static_cast<size_t>(num_lines) * + pixel_data_size); + + unsigned long dstLen = outBuf.size(); + TINYEXR_CHECK_AND_RETURN_C(dstLen > 0, false); + tinyexr::DecompressZfp(reinterpret_cast<float *>(&outBuf.at(0)), width, + num_lines, num_channels, data_ptr, + static_cast<unsigned long>(data_len), + zfp_compression_param); + + // For ZFP_COMPRESSION: + // pixel sample data for channel 0 for scanline 0 + // pixel sample data for channel 1 for scanline 0 + // pixel sample data for channel ... for scanline 0 + // pixel sample data for channel n for scanline 0 + // pixel sample data for channel 0 for scanline 1 + // pixel sample data for channel 1 for scanline 1 + // pixel sample data for channel ... for scanline 1 + // pixel sample data for channel n for scanline 1 + // ... + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + TINYEXR_CHECK_AND_RETURN_C(channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT, false); + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false); + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + const float *line_ptr = reinterpret_cast<float *>( + &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (size_t u = 0; u < static_cast<size_t>(width); u++) { + float val; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + + float *image = reinterpret_cast<float **>(out_images)[c]; + if (line_order == 0) { + image += (static_cast<size_t>(line_no) + v) * + static_cast<size_t>(x_stride) + + u; + } else { + image += (static_cast<size_t>(height) - 1U - + (static_cast<size_t>(line_no) + v)) * + static_cast<size_t>(x_stride) + + u; + } + *image = val; + } + } + } else { + return false; + } + } +#else + (void)attributes; + (void)num_attributes; + (void)num_channels; + return false; +#endif + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) { + for (size_t c = 0; c < num_channels; c++) { + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + const unsigned short *line_ptr = + reinterpret_cast<const unsigned short *>( + data_ptr + v * pixel_data_size * size_t(width) + + channel_offset_list[c] * static_cast<size_t>(width)); + + if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { + unsigned short *outLine = + reinterpret_cast<unsigned short *>(out_images[c]); + if (line_order == 0) { + outLine += (size_t(y) + v) * size_t(x_stride); + } else { + outLine += + (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride); + } + + for (int u = 0; u < width; u++) { + tinyexr::FP16 hf; + + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + outLine[u] = hf.u; + } + } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { + float *outLine = reinterpret_cast<float *>(out_images[c]); + if (line_order == 0) { + outLine += (size_t(y) + v) * size_t(x_stride); + } else { + outLine += + (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride); + } + + if (reinterpret_cast<const unsigned char *>(line_ptr + width) > + (data_ptr + data_len)) { + // Insufficient data size + return false; + } + + for (int u = 0; u < width; u++) { + tinyexr::FP16 hf; + + // address may not be aligned. use byte-wise copy for safety.#76 + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + tinyexr::FP32 f32 = half_to_float(hf); + + outLine[u] = f32.f; + } + } else { + return false; + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + const float *line_ptr = reinterpret_cast<const float *>( + data_ptr + v * pixel_data_size * size_t(width) + + channel_offset_list[c] * static_cast<size_t>(width)); + + float *outLine = reinterpret_cast<float *>(out_images[c]); + if (line_order == 0) { + outLine += (size_t(y) + v) * size_t(x_stride); + } else { + outLine += + (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride); + } + + if (reinterpret_cast<const unsigned char *>(line_ptr + width) > + (data_ptr + data_len)) { + // Insufficient data size + return false; + } + + for (int u = 0; u < width; u++) { + float val; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + + outLine[u] = val; + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + const unsigned int *line_ptr = reinterpret_cast<const unsigned int *>( + data_ptr + v * pixel_data_size * size_t(width) + + channel_offset_list[c] * static_cast<size_t>(width)); + + unsigned int *outLine = + reinterpret_cast<unsigned int *>(out_images[c]); + if (line_order == 0) { + outLine += (size_t(y) + v) * size_t(x_stride); + } else { + outLine += + (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride); + } + + if (reinterpret_cast<const unsigned char *>(line_ptr + width) > + (data_ptr + data_len)) { + // Corrupted data + return false; + } + + for (int u = 0; u < width; u++) { + + unsigned int val; + tinyexr::cpy4(&val, line_ptr + u); + + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + + outLine[u] = val; + } + } + } + } + } + + return true; +} + +static bool DecodeTiledPixelData( + unsigned char **out_images, int *width, int *height, + const int *requested_pixel_types, const unsigned char *data_ptr, + size_t data_len, int compression_type, int line_order, int data_width, + int data_height, int tile_offset_x, int tile_offset_y, int tile_size_x, + int tile_size_y, size_t pixel_data_size, size_t num_attributes, + const EXRAttribute *attributes, size_t num_channels, + const EXRChannelInfo *channels, + const std::vector<size_t> &channel_offset_list) { + // Here, data_width and data_height are the dimensions of the current (sub)level. + if (tile_size_x * tile_offset_x > data_width || + tile_size_y * tile_offset_y > data_height) { + return false; + } + + // Compute actual image size in a tile. + if ((tile_offset_x + 1) * tile_size_x >= data_width) { + (*width) = data_width - (tile_offset_x * tile_size_x); + } else { + (*width) = tile_size_x; + } + + if ((tile_offset_y + 1) * tile_size_y >= data_height) { + (*height) = data_height - (tile_offset_y * tile_size_y); + } else { + (*height) = tile_size_y; + } + + // Image size = tile size. + return DecodePixelData(out_images, requested_pixel_types, data_ptr, data_len, + compression_type, line_order, (*width), tile_size_y, + /* stride */ tile_size_x, /* y */ 0, /* line_no */ 0, + (*height), pixel_data_size, num_attributes, attributes, + num_channels, channels, channel_offset_list); +} + +static bool ComputeChannelLayout(std::vector<size_t> *channel_offset_list, + int *pixel_data_size, size_t *channel_offset, + int num_channels, + const EXRChannelInfo *channels) { + channel_offset_list->resize(static_cast<size_t>(num_channels)); + + (*pixel_data_size) = 0; + (*channel_offset) = 0; + + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + (*channel_offset_list)[c] = (*channel_offset); + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + (*pixel_data_size) += sizeof(unsigned short); + (*channel_offset) += sizeof(unsigned short); + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + (*pixel_data_size) += sizeof(float); + (*channel_offset) += sizeof(float); + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + (*pixel_data_size) += sizeof(unsigned int); + (*channel_offset) += sizeof(unsigned int); + } else { + // ??? + return false; + } + } + return true; +} + +// TODO: Simply return nullptr when failed to allocate? +static unsigned char **AllocateImage(int num_channels, + const EXRChannelInfo *channels, + const int *requested_pixel_types, + int data_width, int data_height, bool *success) { + unsigned char **images = + reinterpret_cast<unsigned char **>(static_cast<float **>( + malloc(sizeof(float *) * static_cast<size_t>(num_channels)))); + + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + images[c] = NULL; + } + + bool valid = true; + + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + size_t data_len = + static_cast<size_t>(data_width) * static_cast<size_t>(data_height); + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + // pixel_data_size += sizeof(unsigned short); + // channel_offset += sizeof(unsigned short); + // Alloc internal image for half type. + if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { + images[c] = + reinterpret_cast<unsigned char *>(static_cast<unsigned short *>( + malloc(sizeof(unsigned short) * data_len))); + } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { + images[c] = reinterpret_cast<unsigned char *>( + static_cast<float *>(malloc(sizeof(float) * data_len))); + } else { + images[c] = NULL; // just in case. + valid = false; + break; + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + // pixel_data_size += sizeof(float); + // channel_offset += sizeof(float); + images[c] = reinterpret_cast<unsigned char *>( + static_cast<float *>(malloc(sizeof(float) * data_len))); + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + // pixel_data_size += sizeof(unsigned int); + // channel_offset += sizeof(unsigned int); + images[c] = reinterpret_cast<unsigned char *>( + static_cast<unsigned int *>(malloc(sizeof(unsigned int) * data_len))); + } else { + images[c] = NULL; // just in case. + valid = false; + break; + } + } + + if (!valid) { + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + if (images[c]) { + free(images[c]); + images[c] = NULL; + } + } + + if (success) { + (*success) = false; + } + } else { + if (success) { + (*success) = true; + } + } + + return images; +} + +#ifdef _WIN32 +static inline std::wstring UTF8ToWchar(const std::string &str) { + int wstr_size = + MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), NULL, 0); + std::wstring wstr(wstr_size, 0); + MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &wstr[0], + (int)wstr.size()); + return wstr; +} +#endif + + +static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, + const EXRVersion *version, std::string *err, + const unsigned char *buf, size_t size) { + const char *marker = reinterpret_cast<const char *>(&buf[0]); + + if (empty_header) { + (*empty_header) = false; + } + + if (version->multipart) { + if (size > 0 && marker[0] == '\0') { + // End of header list. + if (empty_header) { + (*empty_header) = true; + } + return TINYEXR_SUCCESS; + } + } + + // According to the spec, the header of every OpenEXR file must contain at + // least the following attributes: + // + // channels chlist + // compression compression + // dataWindow box2i + // displayWindow box2i + // lineOrder lineOrder + // pixelAspectRatio float + // screenWindowCenter v2f + // screenWindowWidth float + bool has_channels = false; + bool has_compression = false; + bool has_data_window = false; + bool has_display_window = false; + bool has_line_order = false; + bool has_pixel_aspect_ratio = false; + bool has_screen_window_center = false; + bool has_screen_window_width = false; + bool has_name = false; + bool has_type = false; + + info->name.clear(); + info->type.clear(); + + info->data_window.min_x = 0; + info->data_window.min_y = 0; + info->data_window.max_x = 0; + info->data_window.max_y = 0; + info->line_order = 0; // @fixme + info->display_window.min_x = 0; + info->display_window.min_y = 0; + info->display_window.max_x = 0; + info->display_window.max_y = 0; + info->screen_window_center[0] = 0.0f; + info->screen_window_center[1] = 0.0f; + info->screen_window_width = -1.0f; + info->pixel_aspect_ratio = -1.0f; + + info->tiled = 0; + info->tile_size_x = -1; + info->tile_size_y = -1; + info->tile_level_mode = -1; + info->tile_rounding_mode = -1; + + info->attributes.clear(); + + // Read attributes + size_t orig_size = size; + for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) { + if (0 == size) { + if (err) { + (*err) += "Insufficient data size for attributes.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } else if (marker[0] == '\0') { + size--; + break; + } + + std::string attr_name; + std::string attr_type; + std::vector<unsigned char> data; + size_t marker_size; + if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size, + marker, size)) { + if (err) { + (*err) += "Failed to read attribute.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + marker += marker_size; + size -= marker_size; + + // For a multipart file, the version field 9th bit is 0. + if ((version->tiled || version->multipart || version->non_image) && attr_name.compare("tiles") == 0) { + unsigned int x_size, y_size; + unsigned char tile_mode; + if (data.size() != 9) { + if (err) { + (*err) += "(ParseEXRHeader) Invalid attribute data size. Attribute data size must be 9.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + memcpy(&x_size, &data.at(0), sizeof(int)); + memcpy(&y_size, &data.at(4), sizeof(int)); + tile_mode = data[8]; + tinyexr::swap4(&x_size); + tinyexr::swap4(&y_size); + + if (x_size > static_cast<unsigned int>(std::numeric_limits<int>::max()) || + y_size > static_cast<unsigned int>(std::numeric_limits<int>::max())) { + if (err) { + (*err) = "Tile sizes were invalid."; + } + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; + } + + info->tile_size_x = static_cast<int>(x_size); + info->tile_size_y = static_cast<int>(y_size); + + // mode = levelMode + roundingMode * 16 + info->tile_level_mode = tile_mode & 0x3; + info->tile_rounding_mode = (tile_mode >> 4) & 0x1; + info->tiled = 1; + } else if (attr_name.compare("compression") == 0) { + bool ok = false; + if (data[0] < TINYEXR_COMPRESSIONTYPE_PIZ) { + ok = true; + } + + if (data[0] == TINYEXR_COMPRESSIONTYPE_PIZ) { +#if TINYEXR_USE_PIZ + ok = true; +#else + if (err) { + (*err) = "PIZ compression is not supported."; + } + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; +#endif + } + + if (data[0] == TINYEXR_COMPRESSIONTYPE_ZFP) { +#if TINYEXR_USE_ZFP + ok = true; +#else + if (err) { + (*err) = "ZFP compression is not supported."; + } + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; +#endif + } + + if (!ok) { + if (err) { + (*err) = "Unknown compression type."; + } + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; + } + + info->compression_type = static_cast<int>(data[0]); + has_compression = true; + + } else if (attr_name.compare("channels") == 0) { + // name: zero-terminated string, from 1 to 255 bytes long + // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2 + // pLinear: unsigned char, possible values are 0 and 1 + // reserved: three chars, should be zero + // xSampling: int + // ySampling: int + + if (!ReadChannelInfo(info->channels, data)) { + if (err) { + (*err) += "Failed to parse channel info.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + if (info->channels.size() < 1) { + if (err) { + (*err) += "# of channels is zero.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + has_channels = true; + + } else if (attr_name.compare("dataWindow") == 0) { + if (data.size() >= 16) { + memcpy(&info->data_window.min_x, &data.at(0), sizeof(int)); + memcpy(&info->data_window.min_y, &data.at(4), sizeof(int)); + memcpy(&info->data_window.max_x, &data.at(8), sizeof(int)); + memcpy(&info->data_window.max_y, &data.at(12), sizeof(int)); + tinyexr::swap4(&info->data_window.min_x); + tinyexr::swap4(&info->data_window.min_y); + tinyexr::swap4(&info->data_window.max_x); + tinyexr::swap4(&info->data_window.max_y); + has_data_window = true; + } + } else if (attr_name.compare("displayWindow") == 0) { + if (data.size() >= 16) { + memcpy(&info->display_window.min_x, &data.at(0), sizeof(int)); + memcpy(&info->display_window.min_y, &data.at(4), sizeof(int)); + memcpy(&info->display_window.max_x, &data.at(8), sizeof(int)); + memcpy(&info->display_window.max_y, &data.at(12), sizeof(int)); + tinyexr::swap4(&info->display_window.min_x); + tinyexr::swap4(&info->display_window.min_y); + tinyexr::swap4(&info->display_window.max_x); + tinyexr::swap4(&info->display_window.max_y); + + has_display_window = true; + } + } else if (attr_name.compare("lineOrder") == 0) { + if (data.size() >= 1) { + info->line_order = static_cast<int>(data[0]); + has_line_order = true; + } + } else if (attr_name.compare("pixelAspectRatio") == 0) { + if (data.size() >= sizeof(float)) { + memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float)); + tinyexr::swap4(&info->pixel_aspect_ratio); + has_pixel_aspect_ratio = true; + } + } else if (attr_name.compare("screenWindowCenter") == 0) { + if (data.size() >= 8) { + memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float)); + memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float)); + tinyexr::swap4(&info->screen_window_center[0]); + tinyexr::swap4(&info->screen_window_center[1]); + has_screen_window_center = true; + } + } else if (attr_name.compare("screenWindowWidth") == 0) { + if (data.size() >= sizeof(float)) { + memcpy(&info->screen_window_width, &data.at(0), sizeof(float)); + tinyexr::swap4(&info->screen_window_width); + + has_screen_window_width = true; + } + } else if (attr_name.compare("chunkCount") == 0) { + if (data.size() >= sizeof(int)) { + memcpy(&info->chunk_count, &data.at(0), sizeof(int)); + tinyexr::swap4(&info->chunk_count); + } + } else if (attr_name.compare("name") == 0) { + if (!data.empty() && data[0]) { + data.push_back(0); + size_t len = strlen(reinterpret_cast<const char*>(&data[0])); + info->name.resize(len); + info->name.assign(reinterpret_cast<const char*>(&data[0]), len); + has_name = true; + } + } else if (attr_name.compare("type") == 0) { + if (!data.empty() && data[0]) { + data.push_back(0); + size_t len = strlen(reinterpret_cast<const char*>(&data[0])); + info->type.resize(len); + info->type.assign(reinterpret_cast<const char*>(&data[0]), len); + has_type = true; + } + } else { + // Custom attribute(up to TINYEXR_MAX_CUSTOM_ATTRIBUTES) + if (info->attributes.size() < TINYEXR_MAX_CUSTOM_ATTRIBUTES) { + EXRAttribute attrib; +#ifdef _MSC_VER + strncpy_s(attrib.name, attr_name.c_str(), 255); + strncpy_s(attrib.type, attr_type.c_str(), 255); +#else + strncpy(attrib.name, attr_name.c_str(), 255); + strncpy(attrib.type, attr_type.c_str(), 255); +#endif + attrib.name[255] = '\0'; + attrib.type[255] = '\0'; + //std::cout << "i = " << info->attributes.size() << ", dsize = " << data.size() << "\n"; + attrib.size = static_cast<int>(data.size()); + attrib.value = static_cast<unsigned char *>(malloc(data.size())); + memcpy(reinterpret_cast<char *>(attrib.value), &data.at(0), + data.size()); + info->attributes.push_back(attrib); + } + } + } + + // Check if required attributes exist + { + std::stringstream ss_err; + + if (!has_compression) { + ss_err << "\"compression\" attribute not found in the header." + << std::endl; + } + + if (!has_channels) { + ss_err << "\"channels\" attribute not found in the header." << std::endl; + } + + if (!has_line_order) { + ss_err << "\"lineOrder\" attribute not found in the header." << std::endl; + } + + if (!has_display_window) { + ss_err << "\"displayWindow\" attribute not found in the header." + << std::endl; + } + + if (!has_data_window) { + ss_err << "\"dataWindow\" attribute not found in the header or invalid." + << std::endl; + } + + if (!has_pixel_aspect_ratio) { + ss_err << "\"pixelAspectRatio\" attribute not found in the header." + << std::endl; + } + + if (!has_screen_window_width) { + ss_err << "\"screenWindowWidth\" attribute not found in the header." + << std::endl; + } + + if (!has_screen_window_center) { + ss_err << "\"screenWindowCenter\" attribute not found in the header." + << std::endl; + } + + if (version->multipart || version->non_image) { + if (!has_name) { + ss_err << "\"name\" attribute not found in the header." + << std::endl; + } + if (!has_type) { + ss_err << "\"type\" attribute not found in the header." + << std::endl; + } + } + + if (!(ss_err.str().empty())) { + if (err) { + (*err) += ss_err.str(); + } + + return TINYEXR_ERROR_INVALID_HEADER; + } + } + + info->header_len = static_cast<unsigned int>(orig_size - size); + + return TINYEXR_SUCCESS; +} + +// C++ HeaderInfo to C EXRHeader conversion. +static bool ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info, std::string *warn, std::string *err) { + exr_header->pixel_aspect_ratio = info.pixel_aspect_ratio; + exr_header->screen_window_center[0] = info.screen_window_center[0]; + exr_header->screen_window_center[1] = info.screen_window_center[1]; + exr_header->screen_window_width = info.screen_window_width; + exr_header->chunk_count = info.chunk_count; + exr_header->display_window.min_x = info.display_window.min_x; + exr_header->display_window.min_y = info.display_window.min_y; + exr_header->display_window.max_x = info.display_window.max_x; + exr_header->display_window.max_y = info.display_window.max_y; + exr_header->data_window.min_x = info.data_window.min_x; + exr_header->data_window.min_y = info.data_window.min_y; + exr_header->data_window.max_x = info.data_window.max_x; + exr_header->data_window.max_y = info.data_window.max_y; + exr_header->line_order = info.line_order; + exr_header->compression_type = info.compression_type; + exr_header->tiled = info.tiled; + exr_header->tile_size_x = info.tile_size_x; + exr_header->tile_size_y = info.tile_size_y; + exr_header->tile_level_mode = info.tile_level_mode; + exr_header->tile_rounding_mode = info.tile_rounding_mode; + + EXRSetNameAttr(exr_header, info.name.c_str()); + + + if (!info.type.empty()) { + bool valid = true; + if (info.type == "scanlineimage") { + if (exr_header->tiled) { + if (err) { + (*err) += "(ConvertHeader) tiled bit must be off for `scanlineimage` type.\n"; + } + valid = false; + } + } else if (info.type == "tiledimage") { + if (!exr_header->tiled) { + if (err) { + (*err) += "(ConvertHeader) tiled bit must be on for `tiledimage` type.\n"; + } + valid = false; + } + } else if (info.type == "deeptile") { + exr_header->non_image = 1; + if (!exr_header->tiled) { + if (err) { + (*err) += "(ConvertHeader) tiled bit must be on for `deeptile` type.\n"; + } + valid = false; + } + } else if (info.type == "deepscanline") { + exr_header->non_image = 1; + if (exr_header->tiled) { + if (err) { + (*err) += "(ConvertHeader) tiled bit must be off for `deepscanline` type.\n"; + } + //valid = false; + } + } else { + if (warn) { + std::stringstream ss; + ss << "(ConvertHeader) Unsupported or unknown info.type: " << info.type << "\n"; + (*warn) += ss.str(); + } + } + + if (!valid) { + return false; + } + } + + exr_header->num_channels = static_cast<int>(info.channels.size()); + + exr_header->channels = static_cast<EXRChannelInfo *>(malloc( + sizeof(EXRChannelInfo) * static_cast<size_t>(exr_header->num_channels))); + for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) { +#ifdef _MSC_VER + strncpy_s(exr_header->channels[c].name, info.channels[c].name.c_str(), 255); +#else + strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255); +#endif + // manually add '\0' for safety. + exr_header->channels[c].name[255] = '\0'; + + exr_header->channels[c].pixel_type = info.channels[c].pixel_type; + exr_header->channels[c].p_linear = info.channels[c].p_linear; + exr_header->channels[c].x_sampling = info.channels[c].x_sampling; + exr_header->channels[c].y_sampling = info.channels[c].y_sampling; + } + + exr_header->pixel_types = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels))); + for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) { + exr_header->pixel_types[c] = info.channels[c].pixel_type; + } + + // Initially fill with values of `pixel_types` + exr_header->requested_pixel_types = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels))); + for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) { + exr_header->requested_pixel_types[c] = info.channels[c].pixel_type; + } + + exr_header->num_custom_attributes = static_cast<int>(info.attributes.size()); + + if (exr_header->num_custom_attributes > 0) { + // TODO(syoyo): Report warning when # of attributes exceeds + // `TINYEXR_MAX_CUSTOM_ATTRIBUTES` + if (exr_header->num_custom_attributes > TINYEXR_MAX_CUSTOM_ATTRIBUTES) { + exr_header->num_custom_attributes = TINYEXR_MAX_CUSTOM_ATTRIBUTES; + } + + exr_header->custom_attributes = static_cast<EXRAttribute *>(malloc( + sizeof(EXRAttribute) * size_t(exr_header->num_custom_attributes))); + + for (size_t i = 0; i < size_t(exr_header->num_custom_attributes); i++) { + memcpy(exr_header->custom_attributes[i].name, info.attributes[i].name, + 256); + memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type, + 256); + exr_header->custom_attributes[i].size = info.attributes[i].size; + // Just copy pointer + exr_header->custom_attributes[i].value = info.attributes[i].value; + } + + } else { + exr_header->custom_attributes = NULL; + } + + exr_header->header_len = info.header_len; + + return true; +} + +struct OffsetData { + OffsetData() : num_x_levels(0), num_y_levels(0) {} + std::vector<std::vector<std::vector <tinyexr::tinyexr_uint64> > > offsets; + int num_x_levels; + int num_y_levels; +}; + +// -1 = error +static int LevelIndex(int lx, int ly, int tile_level_mode, int num_x_levels) { + switch (tile_level_mode) { + case TINYEXR_TILE_ONE_LEVEL: + return 0; + + case TINYEXR_TILE_MIPMAP_LEVELS: + return lx; + + case TINYEXR_TILE_RIPMAP_LEVELS: + return lx + ly * num_x_levels; + + default: + return -1; + } + return 0; +} + +static int LevelSize(int toplevel_size, int level, int tile_rounding_mode) { + if (level < 0) { + return -1; + } + + int b = static_cast<int>(1u << static_cast<unsigned int>(level)); + int level_size = toplevel_size / b; + + if (tile_rounding_mode == TINYEXR_TILE_ROUND_UP && level_size * b < toplevel_size) + level_size += 1; + + return std::max(level_size, 1); +} + +static int DecodeTiledLevel(EXRImage* exr_image, const EXRHeader* exr_header, + const OffsetData& offset_data, + const std::vector<size_t>& channel_offset_list, + int pixel_data_size, + const unsigned char* head, const size_t size, + std::string* err) { + int num_channels = exr_header->num_channels; + + int level_index = LevelIndex(exr_image->level_x, exr_image->level_y, exr_header->tile_level_mode, offset_data.num_x_levels); + int num_y_tiles = int(offset_data.offsets[size_t(level_index)].size()); + if (num_y_tiles < 1) { + return TINYEXR_ERROR_INVALID_DATA; + } + int num_x_tiles = int(offset_data.offsets[size_t(level_index)][0].size()); + if (num_x_tiles < 1) { + return TINYEXR_ERROR_INVALID_DATA; + } + int num_tiles = num_x_tiles * num_y_tiles; + + int err_code = TINYEXR_SUCCESS; + + enum { + EF_SUCCESS = 0, + EF_INVALID_DATA = 1, + EF_INSUFFICIENT_DATA = 2, + EF_FAILED_TO_DECODE = 4 + }; +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::atomic<unsigned> error_flag(EF_SUCCESS); +#else + unsigned error_flag(EF_SUCCESS); +#endif + + // Although the spec says : "...the data window is subdivided into an array of smaller rectangles...", + // the IlmImf library allows the dimensions of the tile to be larger (or equal) than the dimensions of the data window. +#if 0 + if ((exr_header->tile_size_x > exr_image->width || exr_header->tile_size_y > exr_image->height) && + exr_image->level_x == 0 && exr_image->level_y == 0) { + if (err) { + (*err) += "Failed to decode tile data.\n"; + } + err_code = TINYEXR_ERROR_INVALID_DATA; + } +#endif + exr_image->tiles = static_cast<EXRTile*>( + calloc(sizeof(EXRTile), static_cast<size_t>(num_tiles))); + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::vector<std::thread> workers; + std::atomic<int> tile_count(0); + + int num_threads = std::max(1, int(std::thread::hardware_concurrency())); + if (num_threads > int(num_tiles)) { + num_threads = int(num_tiles); + } + + for (int t = 0; t < num_threads; t++) { + workers.emplace_back(std::thread([&]() + { + int tile_idx = 0; + while ((tile_idx = tile_count++) < num_tiles) { + +#else +#if TINYEXR_USE_OPENMP +#pragma omp parallel for +#endif + for (int tile_idx = 0; tile_idx < num_tiles; tile_idx++) { +#endif + // Allocate memory for each tile. + bool alloc_success = false; + exr_image->tiles[tile_idx].images = tinyexr::AllocateImage( + num_channels, exr_header->channels, + exr_header->requested_pixel_types, exr_header->tile_size_x, + exr_header->tile_size_y, &alloc_success); + + if (!alloc_success) { + error_flag |= EF_INVALID_DATA; + continue; + } + + int x_tile = tile_idx % num_x_tiles; + int y_tile = tile_idx / num_x_tiles; + // 16 byte: tile coordinates + // 4 byte : data size + // ~ : data(uncompressed or compressed) + tinyexr::tinyexr_uint64 offset = offset_data.offsets[size_t(level_index)][size_t(y_tile)][size_t(x_tile)]; + if (offset + sizeof(int) * 5 > size) { + // Insufficient data size. + error_flag |= EF_INSUFFICIENT_DATA; + continue; + } + + size_t data_size = + size_t(size - (offset + sizeof(int) * 5)); + const unsigned char* data_ptr = + reinterpret_cast<const unsigned char*>(head + offset); + + int tile_coordinates[4]; + memcpy(tile_coordinates, data_ptr, sizeof(int) * 4); + tinyexr::swap4(&tile_coordinates[0]); + tinyexr::swap4(&tile_coordinates[1]); + tinyexr::swap4(&tile_coordinates[2]); + tinyexr::swap4(&tile_coordinates[3]); + + if (tile_coordinates[2] != exr_image->level_x) { + // Invalid data. + error_flag |= EF_INVALID_DATA; + continue; + } + if (tile_coordinates[3] != exr_image->level_y) { + // Invalid data. + error_flag |= EF_INVALID_DATA; + continue; + } + + int data_len; + memcpy(&data_len, data_ptr + 16, + sizeof(int)); // 16 = sizeof(tile_coordinates) + tinyexr::swap4(&data_len); + + if (data_len < 2 || size_t(data_len) > data_size) { + // Insufficient data size. + error_flag |= EF_INSUFFICIENT_DATA; + continue; + } + + // Move to data addr: 20 = 16 + 4; + data_ptr += 20; + bool ret = tinyexr::DecodeTiledPixelData( + exr_image->tiles[tile_idx].images, + &(exr_image->tiles[tile_idx].width), + &(exr_image->tiles[tile_idx].height), + exr_header->requested_pixel_types, data_ptr, + static_cast<size_t>(data_len), exr_header->compression_type, + exr_header->line_order, + exr_image->width, exr_image->height, + tile_coordinates[0], tile_coordinates[1], exr_header->tile_size_x, + exr_header->tile_size_y, static_cast<size_t>(pixel_data_size), + static_cast<size_t>(exr_header->num_custom_attributes), + exr_header->custom_attributes, + static_cast<size_t>(exr_header->num_channels), + exr_header->channels, channel_offset_list); + + if (!ret) { + // Failed to decode tile data. + error_flag |= EF_FAILED_TO_DECODE; + } + + exr_image->tiles[tile_idx].offset_x = tile_coordinates[0]; + exr_image->tiles[tile_idx].offset_y = tile_coordinates[1]; + exr_image->tiles[tile_idx].level_x = tile_coordinates[2]; + exr_image->tiles[tile_idx].level_y = tile_coordinates[3]; + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + } + })); + } // num_thread loop + + for (auto& t : workers) { + t.join(); + } + +#else + } // parallel for +#endif + + // Even in the event of an error, the reserved memory may be freed. + exr_image->num_channels = num_channels; + exr_image->num_tiles = static_cast<int>(num_tiles); + + if (error_flag) err_code = TINYEXR_ERROR_INVALID_DATA; + if (err) { + if (error_flag & EF_INSUFFICIENT_DATA) { + (*err) += "Insufficient data length.\n"; + } + if (error_flag & EF_FAILED_TO_DECODE) { + (*err) += "Failed to decode tile data.\n"; + } + } + return err_code; +} + +static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, + const OffsetData& offset_data, + const unsigned char *head, const size_t size, + std::string *err) { + int num_channels = exr_header->num_channels; + + int num_scanline_blocks = 1; + if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) { + num_scanline_blocks = 16; + } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { + num_scanline_blocks = 32; + } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { + num_scanline_blocks = 16; + +#if TINYEXR_USE_ZFP + tinyexr::ZFPCompressionParam zfp_compression_param; + if (!FindZFPCompressionParam(&zfp_compression_param, + exr_header->custom_attributes, + int(exr_header->num_custom_attributes), err)) { + return TINYEXR_ERROR_INVALID_HEADER; + } +#endif + } + + if (exr_header->data_window.max_x < exr_header->data_window.min_x || + exr_header->data_window.max_y < exr_header->data_window.min_y) { + if (err) { + (*err) += "Invalid data window.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + tinyexr_int64 data_width = + static_cast<tinyexr_int64>(exr_header->data_window.max_x) - static_cast<tinyexr_int64>(exr_header->data_window.min_x) + static_cast<tinyexr_int64>(1); + tinyexr_int64 data_height = + static_cast<tinyexr_int64>(exr_header->data_window.max_y) - static_cast<tinyexr_int64>(exr_header->data_window.min_y) + static_cast<tinyexr_int64>(1); + + if (data_width <= 0) { + if (err) { + (*err) += "Invalid data window width.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + if (data_height <= 0) { + if (err) { + (*err) += "Invalid data window height.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + // Do not allow too large data_width and data_height. header invalid? + { + if ((data_width > TINYEXR_DIMENSION_THRESHOLD) || (data_height > TINYEXR_DIMENSION_THRESHOLD)) { + if (err) { + std::stringstream ss; + ss << "data_with or data_height too large. data_width: " << data_width + << ", " + << "data_height = " << data_height << std::endl; + (*err) += ss.str(); + } + return TINYEXR_ERROR_INVALID_DATA; + } + if (exr_header->tiled) { + if ((exr_header->tile_size_x > TINYEXR_DIMENSION_THRESHOLD) || (exr_header->tile_size_y > TINYEXR_DIMENSION_THRESHOLD)) { + if (err) { + std::stringstream ss; + ss << "tile with or tile height too large. tile width: " << exr_header->tile_size_x + << ", " + << "tile height = " << exr_header->tile_size_y << std::endl; + (*err) += ss.str(); + } + return TINYEXR_ERROR_INVALID_DATA; + } + } + } + + const std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data.offsets[0][0]; + size_t num_blocks = offsets.size(); + + std::vector<size_t> channel_offset_list; + int pixel_data_size = 0; + size_t channel_offset = 0; + if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size, + &channel_offset, num_channels, + exr_header->channels)) { + if (err) { + (*err) += "Failed to compute channel layout.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::atomic<bool> invalid_data(false); +#else + bool invalid_data(false); +#endif + + if (exr_header->tiled) { + // value check + if (exr_header->tile_size_x < 0) { + if (err) { + std::stringstream ss; + ss << "Invalid tile size x : " << exr_header->tile_size_x << "\n"; + (*err) += ss.str(); + } + return TINYEXR_ERROR_INVALID_HEADER; + } + + if (exr_header->tile_size_y < 0) { + if (err) { + std::stringstream ss; + ss << "Invalid tile size y : " << exr_header->tile_size_y << "\n"; + (*err) += ss.str(); + } + return TINYEXR_ERROR_INVALID_HEADER; + } + if (exr_header->tile_level_mode != TINYEXR_TILE_RIPMAP_LEVELS) { + EXRImage* level_image = NULL; + for (int level = 0; level < offset_data.num_x_levels; ++level) { + if (!level_image) { + level_image = exr_image; + } else { + level_image->next_level = new EXRImage; + InitEXRImage(level_image->next_level); + level_image = level_image->next_level; + } + level_image->width = + LevelSize(exr_header->data_window.max_x - exr_header->data_window.min_x + 1, level, exr_header->tile_rounding_mode); + if (level_image->width < 1) { + return TINYEXR_ERROR_INVALID_DATA; + } + + level_image->height = + LevelSize(exr_header->data_window.max_y - exr_header->data_window.min_y + 1, level, exr_header->tile_rounding_mode); + + if (level_image->height < 1) { + return TINYEXR_ERROR_INVALID_DATA; + } + + level_image->level_x = level; + level_image->level_y = level; + + int ret = DecodeTiledLevel(level_image, exr_header, + offset_data, + channel_offset_list, + pixel_data_size, + head, size, + err); + if (ret != TINYEXR_SUCCESS) return ret; + } + } else { + EXRImage* level_image = NULL; + for (int level_y = 0; level_y < offset_data.num_y_levels; ++level_y) + for (int level_x = 0; level_x < offset_data.num_x_levels; ++level_x) { + if (!level_image) { + level_image = exr_image; + } else { + level_image->next_level = new EXRImage; + InitEXRImage(level_image->next_level); + level_image = level_image->next_level; + } + + level_image->width = + LevelSize(exr_header->data_window.max_x - exr_header->data_window.min_x + 1, level_x, exr_header->tile_rounding_mode); + if (level_image->width < 1) { + return TINYEXR_ERROR_INVALID_DATA; + } + + level_image->height = + LevelSize(exr_header->data_window.max_y - exr_header->data_window.min_y + 1, level_y, exr_header->tile_rounding_mode); + if (level_image->height < 1) { + return TINYEXR_ERROR_INVALID_DATA; + } + + level_image->level_x = level_x; + level_image->level_y = level_y; + + int ret = DecodeTiledLevel(level_image, exr_header, + offset_data, + channel_offset_list, + pixel_data_size, + head, size, + err); + if (ret != TINYEXR_SUCCESS) return ret; + } + } + } else { // scanline format + // Don't allow too large image(256GB * pixel_data_size or more). Workaround + // for #104. + size_t total_data_len = + size_t(data_width) * size_t(data_height) * size_t(num_channels); + const bool total_data_len_overflown = + sizeof(void *) == 8 ? (total_data_len >= 0x4000000000) : false; + if ((total_data_len == 0) || total_data_len_overflown) { + if (err) { + std::stringstream ss; + ss << "Image data size is zero or too large: width = " << data_width + << ", height = " << data_height << ", channels = " << num_channels + << std::endl; + (*err) += ss.str(); + } + return TINYEXR_ERROR_INVALID_DATA; + } + + bool alloc_success = false; + exr_image->images = tinyexr::AllocateImage( + num_channels, exr_header->channels, exr_header->requested_pixel_types, + int(data_width), int(data_height), &alloc_success); + + if (!alloc_success) { + if (err) { + std::stringstream ss; + ss << "Failed to allocate memory for Images. Maybe EXR header is corrupted or Image data size is too large: width = " << data_width + << ", height = " << data_height << ", channels = " << num_channels + << std::endl; + (*err) += ss.str(); + } + return TINYEXR_ERROR_INVALID_DATA; + } + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::vector<std::thread> workers; + std::atomic<int> y_count(0); + + int num_threads = std::max(1, int(std::thread::hardware_concurrency())); + if (num_threads > int(num_blocks)) { + num_threads = int(num_blocks); + } + + for (int t = 0; t < num_threads; t++) { + workers.emplace_back(std::thread([&]() { + int y = 0; + while ((y = y_count++) < int(num_blocks)) { + +#else + +#if TINYEXR_USE_OPENMP +#pragma omp parallel for +#endif + for (int y = 0; y < static_cast<int>(num_blocks); y++) { + +#endif + size_t y_idx = static_cast<size_t>(y); + + if (offsets[y_idx] + sizeof(int) * 2 > size) { + invalid_data = true; + } else { + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(uncompressed or compressed) + size_t data_size = + size_t(size - (offsets[y_idx] + sizeof(int) * 2)); + const unsigned char *data_ptr = + reinterpret_cast<const unsigned char *>(head + offsets[y_idx]); + + int line_no; + memcpy(&line_no, data_ptr, sizeof(int)); + int data_len; + memcpy(&data_len, data_ptr + 4, sizeof(int)); + tinyexr::swap4(&line_no); + tinyexr::swap4(&data_len); + + if (size_t(data_len) > data_size) { + invalid_data = true; + + } else if ((line_no > (2 << 20)) || (line_no < -(2 << 20))) { + // Too large value. Assume this is invalid + // 2**20 = 1048576 = heuristic value. + invalid_data = true; + } else if (data_len == 0) { + // TODO(syoyo): May be ok to raise the threshold for example + // `data_len < 4` + invalid_data = true; + } else { + // line_no may be negative. + int end_line_no = (std::min)(line_no + num_scanline_blocks, + (exr_header->data_window.max_y + 1)); + + int num_lines = end_line_no - line_no; + + if (num_lines <= 0) { + invalid_data = true; + } else { + // Move to data addr: 8 = 4 + 4; + data_ptr += 8; + + // Adjust line_no with data_window.bmin.y + + // overflow check + tinyexr_int64 lno = + static_cast<tinyexr_int64>(line_no) - + static_cast<tinyexr_int64>(exr_header->data_window.min_y); + if (lno > std::numeric_limits<int>::max()) { + line_no = -1; // invalid + } else if (lno < -std::numeric_limits<int>::max()) { + line_no = -1; // invalid + } else { + line_no -= exr_header->data_window.min_y; + } + + if (line_no < 0) { + invalid_data = true; + } else { + if (!tinyexr::DecodePixelData( + exr_image->images, exr_header->requested_pixel_types, + data_ptr, static_cast<size_t>(data_len), + exr_header->compression_type, exr_header->line_order, + int(data_width), int(data_height), int(data_width), y, line_no, + num_lines, static_cast<size_t>(pixel_data_size), + static_cast<size_t>( + exr_header->num_custom_attributes), + exr_header->custom_attributes, + static_cast<size_t>(exr_header->num_channels), + exr_header->channels, channel_offset_list)) { + invalid_data = true; + } + } + } + } + } + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + } + })); + } + + for (auto &t : workers) { + t.join(); + } +#else + } // omp parallel +#endif + } + + if (invalid_data) { + if (err) { + (*err) += "Invalid/Corrupted data found when decoding pixels.\n"; + } + + // free alloced image. + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + if (exr_image->images[c]) { + free(exr_image->images[c]); + exr_image->images[c] = NULL; + } + } + return TINYEXR_ERROR_INVALID_DATA; + } + + // Overwrite `pixel_type` with `requested_pixel_type`. + { + for (int c = 0; c < exr_header->num_channels; c++) { + exr_header->pixel_types[c] = exr_header->requested_pixel_types[c]; + } + } + + { + exr_image->num_channels = num_channels; + + exr_image->width = int(data_width); + exr_image->height = int(data_height); + } + + return TINYEXR_SUCCESS; +} + +static bool ReconstructLineOffsets( + std::vector<tinyexr::tinyexr_uint64> *offsets, size_t n, + const unsigned char *head, const unsigned char *marker, const size_t size) { + if (head >= marker) { + return false; + } + if (offsets->size() != n) { + return false; + } + + for (size_t i = 0; i < n; i++) { + size_t offset = static_cast<size_t>(marker - head); + // Offset should not exceed whole EXR file/data size. + if ((offset + sizeof(tinyexr::tinyexr_uint64)) >= size) { + return false; + } + + int y; + unsigned int data_len; + + memcpy(&y, marker, sizeof(int)); + memcpy(&data_len, marker + 4, sizeof(unsigned int)); + + if (data_len >= size) { + return false; + } + + tinyexr::swap4(&y); + tinyexr::swap4(&data_len); + + (*offsets)[i] = offset; + + marker += data_len + 8; // 8 = 4 bytes(y) + 4 bytes(data_len) + } + + return true; +} + + +static int FloorLog2(unsigned x) { + // + // For x > 0, floorLog2(y) returns floor(log(x)/log(2)). + // + int y = 0; + while (x > 1) { + y += 1; + x >>= 1u; + } + return y; +} + + +static int CeilLog2(unsigned x) { + // + // For x > 0, ceilLog2(y) returns ceil(log(x)/log(2)). + // + int y = 0; + int r = 0; + while (x > 1) { + if (x & 1) + r = 1; + + y += 1; + x >>= 1u; + } + return y + r; +} + +static int RoundLog2(int x, int tile_rounding_mode) { + return (tile_rounding_mode == TINYEXR_TILE_ROUND_DOWN) ? FloorLog2(static_cast<unsigned>(x)) : CeilLog2(static_cast<unsigned>(x)); +} + +static int CalculateNumXLevels(const EXRHeader* exr_header) { + int min_x = exr_header->data_window.min_x; + int max_x = exr_header->data_window.max_x; + int min_y = exr_header->data_window.min_y; + int max_y = exr_header->data_window.max_y; + + int num = 0; + switch (exr_header->tile_level_mode) { + case TINYEXR_TILE_ONE_LEVEL: + + num = 1; + break; + + case TINYEXR_TILE_MIPMAP_LEVELS: + + { + int w = max_x - min_x + 1; + int h = max_y - min_y + 1; + num = RoundLog2(std::max(w, h), exr_header->tile_rounding_mode) + 1; + } + break; + + case TINYEXR_TILE_RIPMAP_LEVELS: + + { + int w = max_x - min_x + 1; + num = RoundLog2(w, exr_header->tile_rounding_mode) + 1; + } + break; + + default: + + return -1; + } + + return num; +} + +static int CalculateNumYLevels(const EXRHeader* exr_header) { + int min_x = exr_header->data_window.min_x; + int max_x = exr_header->data_window.max_x; + int min_y = exr_header->data_window.min_y; + int max_y = exr_header->data_window.max_y; + int num = 0; + + switch (exr_header->tile_level_mode) { + case TINYEXR_TILE_ONE_LEVEL: + + num = 1; + break; + + case TINYEXR_TILE_MIPMAP_LEVELS: + + { + int w = max_x - min_x + 1; + int h = max_y - min_y + 1; + num = RoundLog2(std::max(w, h), exr_header->tile_rounding_mode) + 1; + } + break; + + case TINYEXR_TILE_RIPMAP_LEVELS: + + { + int h = max_y - min_y + 1; + num = RoundLog2(h, exr_header->tile_rounding_mode) + 1; + } + break; + + default: + + return -1; + } + + return num; +} + +static bool CalculateNumTiles(std::vector<int>& numTiles, + int toplevel_size, + int size, + int tile_rounding_mode) { + for (unsigned i = 0; i < numTiles.size(); i++) { + int l = LevelSize(toplevel_size, int(i), tile_rounding_mode); + if (l < 0) { + return false; + } + TINYEXR_CHECK_AND_RETURN_C(l <= std::numeric_limits<int>::max() - size + 1, false); + + numTiles[i] = (l + size - 1) / size; + } + return true; +} + +static bool PrecalculateTileInfo(std::vector<int>& num_x_tiles, + std::vector<int>& num_y_tiles, + const EXRHeader* exr_header) { + int min_x = exr_header->data_window.min_x; + int max_x = exr_header->data_window.max_x; + int min_y = exr_header->data_window.min_y; + int max_y = exr_header->data_window.max_y; + + int num_x_levels = CalculateNumXLevels(exr_header); + + if (num_x_levels < 0) { + return false; + } + + int num_y_levels = CalculateNumYLevels(exr_header); + + if (num_y_levels < 0) { + return false; + } + + num_x_tiles.resize(size_t(num_x_levels)); + num_y_tiles.resize(size_t(num_y_levels)); + + if (!CalculateNumTiles(num_x_tiles, + max_x - min_x + 1, + exr_header->tile_size_x, + exr_header->tile_rounding_mode)) { + return false; + } + + if (!CalculateNumTiles(num_y_tiles, + max_y - min_y + 1, + exr_header->tile_size_y, + exr_header->tile_rounding_mode)) { + return false; + } + + return true; +} + +static void InitSingleResolutionOffsets(OffsetData& offset_data, size_t num_blocks) { + offset_data.offsets.resize(1); + offset_data.offsets[0].resize(1); + offset_data.offsets[0][0].resize(num_blocks); + offset_data.num_x_levels = 1; + offset_data.num_y_levels = 1; +} + +// Return sum of tile blocks. +// 0 = error +static int InitTileOffsets(OffsetData& offset_data, + const EXRHeader* exr_header, + const std::vector<int>& num_x_tiles, + const std::vector<int>& num_y_tiles) { + int num_tile_blocks = 0; + offset_data.num_x_levels = static_cast<int>(num_x_tiles.size()); + offset_data.num_y_levels = static_cast<int>(num_y_tiles.size()); + switch (exr_header->tile_level_mode) { + case TINYEXR_TILE_ONE_LEVEL: + case TINYEXR_TILE_MIPMAP_LEVELS: + TINYEXR_CHECK_AND_RETURN_C(offset_data.num_x_levels == offset_data.num_y_levels, 0); + offset_data.offsets.resize(size_t(offset_data.num_x_levels)); + + for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) { + offset_data.offsets[l].resize(size_t(num_y_tiles[l])); + + for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) { + offset_data.offsets[l][dy].resize(size_t(num_x_tiles[l])); + num_tile_blocks += num_x_tiles[l]; + } + } + break; + + case TINYEXR_TILE_RIPMAP_LEVELS: + + offset_data.offsets.resize(static_cast<size_t>(offset_data.num_x_levels) * static_cast<size_t>(offset_data.num_y_levels)); + + for (int ly = 0; ly < offset_data.num_y_levels; ++ly) { + for (int lx = 0; lx < offset_data.num_x_levels; ++lx) { + int l = ly * offset_data.num_x_levels + lx; + offset_data.offsets[size_t(l)].resize(size_t(num_y_tiles[size_t(ly)])); + + for (size_t dy = 0; dy < offset_data.offsets[size_t(l)].size(); ++dy) { + offset_data.offsets[size_t(l)][dy].resize(size_t(num_x_tiles[size_t(lx)])); + num_tile_blocks += num_x_tiles[size_t(lx)]; + } + } + } + break; + + default: + return 0; + } + return num_tile_blocks; +} + +static bool IsAnyOffsetsAreInvalid(const OffsetData& offset_data) { + for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) + for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) + for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) + if (reinterpret_cast<const tinyexr::tinyexr_int64&>(offset_data.offsets[l][dy][dx]) <= 0) + return true; + + return false; +} + +static bool isValidTile(const EXRHeader* exr_header, + const OffsetData& offset_data, + int dx, int dy, int lx, int ly) { + if (lx < 0 || ly < 0 || dx < 0 || dy < 0) return false; + int num_x_levels = offset_data.num_x_levels; + int num_y_levels = offset_data.num_y_levels; + switch (exr_header->tile_level_mode) { + case TINYEXR_TILE_ONE_LEVEL: + + if (lx == 0 && + ly == 0 && + offset_data.offsets.size() > 0 && + offset_data.offsets[0].size() > static_cast<size_t>(dy) && + offset_data.offsets[0][size_t(dy)].size() > static_cast<size_t>(dx)) { + return true; + } + + break; + + case TINYEXR_TILE_MIPMAP_LEVELS: + + if (lx < num_x_levels && + ly < num_y_levels && + offset_data.offsets.size() > static_cast<size_t>(lx) && + offset_data.offsets[size_t(lx)].size() > static_cast<size_t>(dy) && + offset_data.offsets[size_t(lx)][size_t(dy)].size() > static_cast<size_t>(dx)) { + return true; + } + + break; + + case TINYEXR_TILE_RIPMAP_LEVELS: + { + size_t idx = static_cast<size_t>(lx) + static_cast<size_t>(ly)* static_cast<size_t>(num_x_levels); + if (lx < num_x_levels && + ly < num_y_levels && + (offset_data.offsets.size() > idx) && + offset_data.offsets[idx].size() > static_cast<size_t>(dy) && + offset_data.offsets[idx][size_t(dy)].size() > static_cast<size_t>(dx)) { + return true; + } + } + + break; + + default: + + return false; + } + + return false; +} + +static bool ReconstructTileOffsets(OffsetData& offset_data, + const EXRHeader* exr_header, + const unsigned char* head, const unsigned char* marker, const size_t /*size*/, + bool isMultiPartFile, + bool isDeep) { + int numXLevels = offset_data.num_x_levels; + for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) { + for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) { + for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) { + tinyexr::tinyexr_uint64 tileOffset = tinyexr::tinyexr_uint64(marker - head); + + if (isMultiPartFile) { + //int partNumber; + marker += sizeof(int); + } + + int tileX; + memcpy(&tileX, marker, sizeof(int)); + tinyexr::swap4(&tileX); + marker += sizeof(int); + + int tileY; + memcpy(&tileY, marker, sizeof(int)); + tinyexr::swap4(&tileY); + marker += sizeof(int); + + int levelX; + memcpy(&levelX, marker, sizeof(int)); + tinyexr::swap4(&levelX); + marker += sizeof(int); + + int levelY; + memcpy(&levelY, marker, sizeof(int)); + tinyexr::swap4(&levelY); + marker += sizeof(int); + + if (isDeep) { + tinyexr::tinyexr_int64 packed_offset_table_size; + memcpy(&packed_offset_table_size, marker, sizeof(tinyexr::tinyexr_int64)); + tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64*>(&packed_offset_table_size)); + marker += sizeof(tinyexr::tinyexr_int64); + + tinyexr::tinyexr_int64 packed_sample_size; + memcpy(&packed_sample_size, marker, sizeof(tinyexr::tinyexr_int64)); + tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64*>(&packed_sample_size)); + marker += sizeof(tinyexr::tinyexr_int64); + + // next Int64 is unpacked sample size - skip that too + marker += packed_offset_table_size + packed_sample_size + 8; + + } else { + + int dataSize; + memcpy(&dataSize, marker, sizeof(int)); + tinyexr::swap4(&dataSize); + marker += sizeof(int); + marker += dataSize; + } + + if (!isValidTile(exr_header, offset_data, + tileX, tileY, levelX, levelY)) { + return false; + } + + int level_idx = LevelIndex(levelX, levelY, exr_header->tile_level_mode, numXLevels); + if (level_idx < 0) { + return false; + } + offset_data.offsets[size_t(level_idx)][size_t(tileY)][size_t(tileX)] = tileOffset; + } + } + } + return true; +} + +// marker output is also +static int ReadOffsets(OffsetData& offset_data, + const unsigned char* head, + const unsigned char*& marker, + const size_t size, + const char** err) { + for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) { + for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) { + for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) { + tinyexr::tinyexr_uint64 offset; + if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) { + tinyexr::SetErrorMessage("Insufficient data size in offset table.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64)); + tinyexr::swap8(&offset); + if (offset >= size) { + tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + marker += sizeof(tinyexr::tinyexr_uint64); // = 8 + offset_data.offsets[l][dy][dx] = offset; + } + } + } + return TINYEXR_SUCCESS; +} + +static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, + const unsigned char *head, + const unsigned char *marker, const size_t size, + const char **err) { + if (exr_image == NULL || exr_header == NULL || head == NULL || + marker == NULL || (size <= tinyexr::kEXRVersionSize)) { + tinyexr::SetErrorMessage("Invalid argument for DecodeEXRImage().", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + int num_scanline_blocks = 1; + if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) { + num_scanline_blocks = 16; + } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { + num_scanline_blocks = 32; + } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { + num_scanline_blocks = 16; + } + + if (exr_header->data_window.max_x < exr_header->data_window.min_x || + exr_header->data_window.max_x - exr_header->data_window.min_x == + std::numeric_limits<int>::max()) { + // Issue 63 + tinyexr::SetErrorMessage("Invalid data width value", err); + return TINYEXR_ERROR_INVALID_DATA; + } + tinyexr_int64 data_width = + static_cast<tinyexr_int64>(exr_header->data_window.max_x) - static_cast<tinyexr_int64>(exr_header->data_window.min_x) + static_cast<tinyexr_int64>(1); + if (data_width <= 0) { + tinyexr::SetErrorMessage("Invalid data window width value", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + if (exr_header->data_window.max_y < exr_header->data_window.min_y || + exr_header->data_window.max_y - exr_header->data_window.min_y == + std::numeric_limits<int>::max()) { + tinyexr::SetErrorMessage("Invalid data height value", err); + return TINYEXR_ERROR_INVALID_DATA; + } + tinyexr_int64 data_height = + static_cast<tinyexr_int64>(exr_header->data_window.max_y) - static_cast<tinyexr_int64>(exr_header->data_window.min_y) + static_cast<tinyexr_int64>(1); + + if (data_height <= 0) { + tinyexr::SetErrorMessage("Invalid data window height value", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + // Do not allow too large data_width and data_height. header invalid? + { + if (data_width > TINYEXR_DIMENSION_THRESHOLD) { + tinyexr::SetErrorMessage("data width too large.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + if (data_height > TINYEXR_DIMENSION_THRESHOLD) { + tinyexr::SetErrorMessage("data height too large.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + + if (exr_header->tiled) { + if (exr_header->tile_size_x > TINYEXR_DIMENSION_THRESHOLD) { + tinyexr::SetErrorMessage("tile width too large.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + if (exr_header->tile_size_y > TINYEXR_DIMENSION_THRESHOLD) { + tinyexr::SetErrorMessage("tile height too large.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + + // Read offset tables. + OffsetData offset_data; + size_t num_blocks = 0; + // For a multi-resolution image, the size of the offset table will be calculated from the other attributes of the header. + // If chunk_count > 0 then chunk_count must be equal to the calculated tile count. + if (exr_header->tiled) { + { + std::vector<int> num_x_tiles, num_y_tiles; + if (!PrecalculateTileInfo(num_x_tiles, num_y_tiles, exr_header)) { + tinyexr::SetErrorMessage("Failed to precalculate tile info.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + num_blocks = size_t(InitTileOffsets(offset_data, exr_header, num_x_tiles, num_y_tiles)); + if (exr_header->chunk_count > 0) { + if (exr_header->chunk_count != static_cast<int>(num_blocks)) { + tinyexr::SetErrorMessage("Invalid offset table size.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + } + + int ret = ReadOffsets(offset_data, head, marker, size, err); + if (ret != TINYEXR_SUCCESS) return ret; + if (IsAnyOffsetsAreInvalid(offset_data)) { + if (!ReconstructTileOffsets(offset_data, exr_header, + head, marker, size, + exr_header->multipart, exr_header->non_image)) { + + tinyexr::SetErrorMessage("Invalid Tile Offsets data.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + } else if (exr_header->chunk_count > 0) { + // Use `chunkCount` attribute. + num_blocks = static_cast<size_t>(exr_header->chunk_count); + InitSingleResolutionOffsets(offset_data, num_blocks); + } else { + num_blocks = static_cast<size_t>(data_height) / + static_cast<size_t>(num_scanline_blocks); + if (num_blocks * static_cast<size_t>(num_scanline_blocks) < + static_cast<size_t>(data_height)) { + num_blocks++; + } + + InitSingleResolutionOffsets(offset_data, num_blocks); + } + + if (!exr_header->tiled) { + std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data.offsets[0][0]; + for (size_t y = 0; y < num_blocks; y++) { + tinyexr::tinyexr_uint64 offset; + // Issue #81 + if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) { + tinyexr::SetErrorMessage("Insufficient data size in offset table.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64)); + tinyexr::swap8(&offset); + if (offset >= size) { + tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + marker += sizeof(tinyexr::tinyexr_uint64); // = 8 + offsets[y] = offset; + } + + // If line offsets are invalid, we try to reconstruct it. + // See OpenEXR/IlmImf/ImfScanLineInputFile.cpp::readLineOffsets() for details. + for (size_t y = 0; y < num_blocks; y++) { + if (offsets[y] <= 0) { + // TODO(syoyo) Report as warning? + // if (err) { + // stringstream ss; + // ss << "Incomplete lineOffsets." << std::endl; + // (*err) += ss.str(); + //} + bool ret = + ReconstructLineOffsets(&offsets, num_blocks, head, marker, size); + if (ret) { + // OK + break; + } else { + tinyexr::SetErrorMessage( + "Cannot reconstruct lineOffset table in DecodeEXRImage.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + } + } + + { + std::string e; + int ret = DecodeChunk(exr_image, exr_header, offset_data, head, size, &e); + + if (ret != TINYEXR_SUCCESS) { + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } + +#if 1 + FreeEXRImage(exr_image); +#else + // release memory(if exists) + if ((exr_header->num_channels > 0) && exr_image && exr_image->images) { + for (size_t c = 0; c < size_t(exr_header->num_channels); c++) { + if (exr_image->images[c]) { + free(exr_image->images[c]); + exr_image->images[c] = NULL; + } + } + free(exr_image->images); + exr_image->images = NULL; + } +#endif + } + + return ret; + } +} + +static void GetLayers(const EXRHeader &exr_header, + std::vector<std::string> &layer_names) { + // Naive implementation + // Group channels by layers + // go over all channel names, split by periods + // collect unique names + layer_names.clear(); + for (int c = 0; c < exr_header.num_channels; c++) { + std::string full_name(exr_header.channels[c].name); + const size_t pos = full_name.find_last_of('.'); + if (pos != std::string::npos && pos != 0 && pos + 1 < full_name.size()) { + full_name.erase(pos); + if (std::find(layer_names.begin(), layer_names.end(), full_name) == + layer_names.end()) + layer_names.push_back(full_name); + } + } +} + +struct LayerChannel { + explicit LayerChannel(size_t i, std::string n) : index(i), name(n) {} + size_t index; + std::string name; +}; + +static void ChannelsInLayer(const EXRHeader &exr_header, + const std::string &layer_name, + std::vector<LayerChannel> &channels) { + channels.clear(); + //std::cout << "layer_name = " << layer_name << "\n"; + for (int c = 0; c < exr_header.num_channels; c++) { + //std::cout << "chan[" << c << "] = " << exr_header.channels[c].name << "\n"; + std::string ch_name(exr_header.channels[c].name); + if (layer_name.empty()) { + const size_t pos = ch_name.find_last_of('.'); + if (pos != std::string::npos && pos < ch_name.size()) { + if (pos != 0) continue; + ch_name = ch_name.substr(pos + 1); + } + } else { + const size_t pos = ch_name.find(layer_name + '.'); + if (pos == std::string::npos) continue; + if (pos == 0) { + ch_name = ch_name.substr(layer_name.size() + 1); + } + } + LayerChannel ch(size_t(c), ch_name); + channels.push_back(ch); + } +} + +} // namespace tinyexr + +int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, + const char **err) { + EXRVersion exr_version; + EXRHeader exr_header; + InitEXRHeader(&exr_header); + + { + int ret = ParseEXRVersionFromFile(&exr_version, filename); + if (ret != TINYEXR_SUCCESS) { + tinyexr::SetErrorMessage("Invalid EXR header.", err); + return ret; + } + + if (exr_version.multipart || exr_version.non_image) { + tinyexr::SetErrorMessage( + "Loading multipart or DeepImage is not supported in LoadEXR() API", + err); + return TINYEXR_ERROR_INVALID_DATA; // @fixme. + } + } + + int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err); + if (ret != TINYEXR_SUCCESS) { + FreeEXRHeader(&exr_header); + return ret; + } + + std::vector<std::string> layer_vec; + tinyexr::GetLayers(exr_header, layer_vec); + + (*num_layers) = int(layer_vec.size()); + (*layer_names) = static_cast<const char **>( + malloc(sizeof(const char *) * static_cast<size_t>(layer_vec.size()))); + for (size_t c = 0; c < static_cast<size_t>(layer_vec.size()); c++) { +#ifdef _MSC_VER + (*layer_names)[c] = _strdup(layer_vec[c].c_str()); +#else + (*layer_names)[c] = strdup(layer_vec[c].c_str()); +#endif + } + + FreeEXRHeader(&exr_header); + return TINYEXR_SUCCESS; +} + +int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, + const char **err) { + return LoadEXRWithLayer(out_rgba, width, height, filename, + /* layername */ NULL, err); +} + +int LoadEXRWithLayer(float **out_rgba, int *width, int *height, + const char *filename, const char *layername, + const char **err) { + if (out_rgba == NULL) { + tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + EXRVersion exr_version; + EXRImage exr_image; + EXRHeader exr_header; + InitEXRHeader(&exr_header); + InitEXRImage(&exr_image); + + { + int ret = ParseEXRVersionFromFile(&exr_version, filename); + if (ret != TINYEXR_SUCCESS) { + std::stringstream ss; + ss << "Failed to open EXR file or read version info from EXR file. code(" + << ret << ")"; + tinyexr::SetErrorMessage(ss.str(), err); + return ret; + } + + if (exr_version.multipart || exr_version.non_image) { + tinyexr::SetErrorMessage( + "Loading multipart or DeepImage is not supported in LoadEXR() API", + err); + return TINYEXR_ERROR_INVALID_DATA; // @fixme. + } + } + + { + int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err); + if (ret != TINYEXR_SUCCESS) { + FreeEXRHeader(&exr_header); + return ret; + } + } + + // Read HALF channel as FLOAT. + for (int i = 0; i < exr_header.num_channels; i++) { + if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) { + exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; + } + } + + // TODO: Probably limit loading to layers (channels) selected by layer index + { + int ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename, err); + if (ret != TINYEXR_SUCCESS) { + FreeEXRHeader(&exr_header); + return ret; + } + } + + // RGBA + int idxR = -1; + int idxG = -1; + int idxB = -1; + int idxA = -1; + + std::vector<std::string> layer_names; + tinyexr::GetLayers(exr_header, layer_names); + + std::vector<tinyexr::LayerChannel> channels; + tinyexr::ChannelsInLayer( + exr_header, layername == NULL ? "" : std::string(layername), channels); + + + if (channels.size() < 1) { + if (layername == NULL) { + tinyexr::SetErrorMessage("Layer Not Found. Seems EXR contains channels with layer(e.g. `diffuse.R`). if you are using LoadEXR(), please try LoadEXRWithLayer(). LoadEXR() cannot load EXR having channels with layer.", err); + + } else { + tinyexr::SetErrorMessage("Layer Not Found", err); + } + FreeEXRHeader(&exr_header); + FreeEXRImage(&exr_image); + return TINYEXR_ERROR_LAYER_NOT_FOUND; + } + + size_t ch_count = channels.size() < 4 ? channels.size() : 4; + for (size_t c = 0; c < ch_count; c++) { + const tinyexr::LayerChannel &ch = channels[c]; + + if (ch.name == "R") { + idxR = int(ch.index); + } else if (ch.name == "G") { + idxG = int(ch.index); + } else if (ch.name == "B") { + idxB = int(ch.index); + } else if (ch.name == "A") { + idxA = int(ch.index); + } + } + + if (channels.size() == 1) { + int chIdx = int(channels.front().index); + // Grayscale channel only. + + (*out_rgba) = reinterpret_cast<float *>( + malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height))); + + if (exr_header.tiled) { + const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x); + const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y); + for (int it = 0; it < exr_image.num_tiles; it++) { + for (size_t j = 0; j < tile_size_y; j++) { + for (size_t i = 0; i < tile_size_x; i++) { + const size_t ii = + static_cast<size_t>(exr_image.tiles[it].offset_x) * tile_size_x + + i; + const size_t jj = + static_cast<size_t>(exr_image.tiles[it].offset_y) * tile_size_y + + j; + const size_t idx = ii + jj * static_cast<size_t>(exr_image.width); + + // out of region check. + if (ii >= static_cast<size_t>(exr_image.width)) { + continue; + } + if (jj >= static_cast<size_t>(exr_image.height)) { + continue; + } + const size_t srcIdx = i + j * tile_size_x; + unsigned char **src = exr_image.tiles[it].images; + (*out_rgba)[4 * idx + 0] = + reinterpret_cast<float **>(src)[chIdx][srcIdx]; + (*out_rgba)[4 * idx + 1] = + reinterpret_cast<float **>(src)[chIdx][srcIdx]; + (*out_rgba)[4 * idx + 2] = + reinterpret_cast<float **>(src)[chIdx][srcIdx]; + (*out_rgba)[4 * idx + 3] = + reinterpret_cast<float **>(src)[chIdx][srcIdx]; + } + } + } + } else { + const size_t pixel_size = static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height); + for (size_t i = 0; i < pixel_size; i++) { + const float val = + reinterpret_cast<float **>(exr_image.images)[chIdx][i]; + (*out_rgba)[4 * i + 0] = val; + (*out_rgba)[4 * i + 1] = val; + (*out_rgba)[4 * i + 2] = val; + (*out_rgba)[4 * i + 3] = val; + } + } + } else { + // Assume RGB(A) + + if (idxR == -1) { + tinyexr::SetErrorMessage("R channel not found", err); + + FreeEXRHeader(&exr_header); + FreeEXRImage(&exr_image); + return TINYEXR_ERROR_INVALID_DATA; + } + + if (idxG == -1) { + tinyexr::SetErrorMessage("G channel not found", err); + FreeEXRHeader(&exr_header); + FreeEXRImage(&exr_image); + return TINYEXR_ERROR_INVALID_DATA; + } + + if (idxB == -1) { + tinyexr::SetErrorMessage("B channel not found", err); + FreeEXRHeader(&exr_header); + FreeEXRImage(&exr_image); + return TINYEXR_ERROR_INVALID_DATA; + } + + (*out_rgba) = reinterpret_cast<float *>( + malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height))); + if (exr_header.tiled) { + const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x); + const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y); + for (int it = 0; it < exr_image.num_tiles; it++) { + for (size_t j = 0; j < tile_size_y; j++) { + for (size_t i = 0; i < tile_size_x; i++) { + const size_t ii = + static_cast<size_t>(exr_image.tiles[it].offset_x) * + tile_size_x + + i; + const size_t jj = + static_cast<size_t>(exr_image.tiles[it].offset_y) * + tile_size_y + + j; + const size_t idx = ii + jj * static_cast<size_t>(exr_image.width); + + // out of region check. + if (ii >= static_cast<size_t>(exr_image.width)) { + continue; + } + if (jj >= static_cast<size_t>(exr_image.height)) { + continue; + } + const size_t srcIdx = i + j * tile_size_x; + unsigned char **src = exr_image.tiles[it].images; + (*out_rgba)[4 * idx + 0] = + reinterpret_cast<float **>(src)[idxR][srcIdx]; + (*out_rgba)[4 * idx + 1] = + reinterpret_cast<float **>(src)[idxG][srcIdx]; + (*out_rgba)[4 * idx + 2] = + reinterpret_cast<float **>(src)[idxB][srcIdx]; + if (idxA != -1) { + (*out_rgba)[4 * idx + 3] = + reinterpret_cast<float **>(src)[idxA][srcIdx]; + } else { + (*out_rgba)[4 * idx + 3] = 1.0; + } + } + } + } + } else { + const size_t pixel_size = static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height); + for (size_t i = 0; i < pixel_size; i++) { + (*out_rgba)[4 * i + 0] = + reinterpret_cast<float **>(exr_image.images)[idxR][i]; + (*out_rgba)[4 * i + 1] = + reinterpret_cast<float **>(exr_image.images)[idxG][i]; + (*out_rgba)[4 * i + 2] = + reinterpret_cast<float **>(exr_image.images)[idxB][i]; + if (idxA != -1) { + (*out_rgba)[4 * i + 3] = + reinterpret_cast<float **>(exr_image.images)[idxA][i]; + } else { + (*out_rgba)[4 * i + 3] = 1.0; + } + } + } + } + + (*width) = exr_image.width; + (*height) = exr_image.height; + + FreeEXRHeader(&exr_header); + FreeEXRImage(&exr_image); + + return TINYEXR_SUCCESS; +} + +int IsEXR(const char *filename) { + EXRVersion exr_version; + + int ret = ParseEXRVersionFromFile(&exr_version, filename); + if (ret != TINYEXR_SUCCESS) { + return ret; + } + + return TINYEXR_SUCCESS; +} + +int IsEXRFromMemory(const unsigned char *memory, size_t size) { + EXRVersion exr_version; + + int ret = ParseEXRVersionFromMemory(&exr_version, memory, size); + if (ret != TINYEXR_SUCCESS) { + return ret; + } + + return TINYEXR_SUCCESS; +} + +int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version, + const unsigned char *memory, size_t size, + const char **err) { + if (memory == NULL || exr_header == NULL) { + tinyexr::SetErrorMessage( + "Invalid argument. `memory` or `exr_header` argument is null in " + "ParseEXRHeaderFromMemory()", + err); + + // Invalid argument + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if (size < tinyexr::kEXRVersionSize) { + tinyexr::SetErrorMessage("Insufficient header/data size.\n", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + const unsigned char *marker = memory + tinyexr::kEXRVersionSize; + size_t marker_size = size - tinyexr::kEXRVersionSize; + + tinyexr::HeaderInfo info; + info.clear(); + + int ret; + { + std::string err_str; + ret = ParseEXRHeader(&info, NULL, version, &err_str, marker, marker_size); + + if (ret != TINYEXR_SUCCESS) { + if (err && !err_str.empty()) { + tinyexr::SetErrorMessage(err_str, err); + } + } + } + + { + std::string warn; + std::string err_str; + + if (!ConvertHeader(exr_header, info, &warn, &err_str)) { + // release mem + for (size_t i = 0; i < info.attributes.size(); i++) { + if (info.attributes[i].value) { + free(info.attributes[i].value); + } + } + if (err && !err_str.empty()) { + tinyexr::SetErrorMessage(err_str, err); + } + ret = TINYEXR_ERROR_INVALID_HEADER; + } + } + + exr_header->multipart = version->multipart ? 1 : 0; + exr_header->non_image = version->non_image ? 1 : 0; + + return ret; +} + +int LoadEXRFromMemory(float **out_rgba, int *width, int *height, + const unsigned char *memory, size_t size, + const char **err) { + if (out_rgba == NULL || memory == NULL) { + tinyexr::SetErrorMessage("Invalid argument for LoadEXRFromMemory", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + EXRVersion exr_version; + EXRImage exr_image; + EXRHeader exr_header; + + InitEXRHeader(&exr_header); + + int ret = ParseEXRVersionFromMemory(&exr_version, memory, size); + if (ret != TINYEXR_SUCCESS) { + std::stringstream ss; + ss << "Failed to parse EXR version. code(" << ret << ")"; + tinyexr::SetErrorMessage(ss.str(), err); + return ret; + } + + ret = ParseEXRHeaderFromMemory(&exr_header, &exr_version, memory, size, err); + if (ret != TINYEXR_SUCCESS) { + return ret; + } + + // Read HALF channel as FLOAT. + for (int i = 0; i < exr_header.num_channels; i++) { + if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) { + exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; + } + } + + InitEXRImage(&exr_image); + ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err); + if (ret != TINYEXR_SUCCESS) { + return ret; + } + + // RGBA + int idxR = -1; + int idxG = -1; + int idxB = -1; + int idxA = -1; + for (int c = 0; c < exr_header.num_channels; c++) { + if (strcmp(exr_header.channels[c].name, "R") == 0) { + idxR = c; + } else if (strcmp(exr_header.channels[c].name, "G") == 0) { + idxG = c; + } else if (strcmp(exr_header.channels[c].name, "B") == 0) { + idxB = c; + } else if (strcmp(exr_header.channels[c].name, "A") == 0) { + idxA = c; + } + } + + // TODO(syoyo): Refactor removing same code as used in LoadEXR(). + if (exr_header.num_channels == 1) { + // Grayscale channel only. + + (*out_rgba) = reinterpret_cast<float *>( + malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height))); + + if (exr_header.tiled) { + const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x); + const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y); + for (int it = 0; it < exr_image.num_tiles; it++) { + for (size_t j = 0; j < tile_size_y; j++) { + for (size_t i = 0; i < tile_size_x; i++) { + const size_t ii = + static_cast<size_t>(exr_image.tiles[it].offset_x) * + tile_size_x + + i; + const size_t jj = + static_cast<size_t>(exr_image.tiles[it].offset_y) * + tile_size_y + + j; + const size_t idx = ii + jj * static_cast<size_t>(exr_image.width); + + // out of region check. + if (ii >= static_cast<size_t>(exr_image.width)) { + continue; + } + if (jj >= static_cast<size_t>(exr_image.height)) { + continue; + } + const size_t srcIdx = i + j * tile_size_x; + unsigned char **src = exr_image.tiles[it].images; + (*out_rgba)[4 * idx + 0] = + reinterpret_cast<float **>(src)[0][srcIdx]; + (*out_rgba)[4 * idx + 1] = + reinterpret_cast<float **>(src)[0][srcIdx]; + (*out_rgba)[4 * idx + 2] = + reinterpret_cast<float **>(src)[0][srcIdx]; + (*out_rgba)[4 * idx + 3] = + reinterpret_cast<float **>(src)[0][srcIdx]; + } + } + } + } else { + const size_t pixel_size = static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height); + for (size_t i = 0; i < pixel_size; i++) { + const float val = reinterpret_cast<float **>(exr_image.images)[0][i]; + (*out_rgba)[4 * i + 0] = val; + (*out_rgba)[4 * i + 1] = val; + (*out_rgba)[4 * i + 2] = val; + (*out_rgba)[4 * i + 3] = val; + } + } + + } else { + // TODO(syoyo): Support non RGBA image. + + if (idxR == -1) { + tinyexr::SetErrorMessage("R channel not found", err); + + // @todo { free exr_image } + return TINYEXR_ERROR_INVALID_DATA; + } + + if (idxG == -1) { + tinyexr::SetErrorMessage("G channel not found", err); + // @todo { free exr_image } + return TINYEXR_ERROR_INVALID_DATA; + } + + if (idxB == -1) { + tinyexr::SetErrorMessage("B channel not found", err); + // @todo { free exr_image } + return TINYEXR_ERROR_INVALID_DATA; + } + + (*out_rgba) = reinterpret_cast<float *>( + malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height))); + + if (exr_header.tiled) { + const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x); + const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y); + for (int it = 0; it < exr_image.num_tiles; it++) { + for (size_t j = 0; j < tile_size_y; j++) + for (size_t i = 0; i < tile_size_x; i++) { + const size_t ii = + static_cast<size_t>(exr_image.tiles[it].offset_x) * + tile_size_x + + i; + const size_t jj = + static_cast<size_t>(exr_image.tiles[it].offset_y) * + tile_size_y + + j; + const size_t idx = ii + jj * static_cast<size_t>(exr_image.width); + + // out of region check. + if (ii >= static_cast<size_t>(exr_image.width)) { + continue; + } + if (jj >= static_cast<size_t>(exr_image.height)) { + continue; + } + const size_t srcIdx = i + j * tile_size_x; + unsigned char **src = exr_image.tiles[it].images; + (*out_rgba)[4 * idx + 0] = + reinterpret_cast<float **>(src)[idxR][srcIdx]; + (*out_rgba)[4 * idx + 1] = + reinterpret_cast<float **>(src)[idxG][srcIdx]; + (*out_rgba)[4 * idx + 2] = + reinterpret_cast<float **>(src)[idxB][srcIdx]; + if (idxA != -1) { + (*out_rgba)[4 * idx + 3] = + reinterpret_cast<float **>(src)[idxA][srcIdx]; + } else { + (*out_rgba)[4 * idx + 3] = 1.0; + } + } + } + } else { + const size_t pixel_size = static_cast<size_t>(exr_image.width) * + static_cast<size_t>(exr_image.height); + for (size_t i = 0; i < pixel_size; i++) { + (*out_rgba)[4 * i + 0] = + reinterpret_cast<float **>(exr_image.images)[idxR][i]; + (*out_rgba)[4 * i + 1] = + reinterpret_cast<float **>(exr_image.images)[idxG][i]; + (*out_rgba)[4 * i + 2] = + reinterpret_cast<float **>(exr_image.images)[idxB][i]; + if (idxA != -1) { + (*out_rgba)[4 * i + 3] = + reinterpret_cast<float **>(exr_image.images)[idxA][i]; + } else { + (*out_rgba)[4 * i + 3] = 1.0; + } + } + } + } + + (*width) = exr_image.width; + (*height) = exr_image.height; + + FreeEXRHeader(&exr_header); + FreeEXRImage(&exr_image); + + return TINYEXR_SUCCESS; +} + +// Represents a read-only file mapped to an address space in memory. +// If no memory-mapping API is available, falls back to allocating a buffer +// with a copy of the file's data. +struct MemoryMappedFile { + unsigned char *data; // To the start of the file's data. + size_t size; // The size of the file in bytes. +#ifdef TINYEXR_USE_WIN32_MMAP + HANDLE windows_file; + HANDLE windows_file_mapping; +#elif defined(TINYEXR_USE_POSIX_MMAP) + int posix_descriptor; +#endif + + // MemoryMappedFile's constructor tries to map memory to a file. + // If this succeeds, valid() will return true and all fields + // are usable; otherwise, valid() will return false. + MemoryMappedFile(const char *filename) { + data = NULL; + size = 0; +#ifdef TINYEXR_USE_WIN32_MMAP + windows_file_mapping = NULL; + windows_file = + CreateFileW(tinyexr::UTF8ToWchar(filename).c_str(), // lpFileName + GENERIC_READ, // dwDesiredAccess + FILE_SHARE_READ, // dwShareMode + NULL, // lpSecurityAttributes + OPEN_EXISTING, // dwCreationDisposition + FILE_ATTRIBUTE_READONLY, // dwFlagsAndAttributes + NULL); // hTemplateFile + if (windows_file == INVALID_HANDLE_VALUE) { + return; + } + + windows_file_mapping = CreateFileMapping(windows_file, // hFile + NULL, // lpFileMappingAttributes + PAGE_READONLY, // flProtect + 0, // dwMaximumSizeHigh + 0, // dwMaximumSizeLow + NULL); // lpName + if (windows_file_mapping == NULL) { + return; + } + + data = reinterpret_cast<unsigned char *>( + MapViewOfFile(windows_file_mapping, // hFileMappingObject + FILE_MAP_READ, // dwDesiredAccess + 0, // dwFileOffsetHigh + 0, // dwFileOffsetLow + 0)); // dwNumberOfBytesToMap + if (!data) { + return; + } + + LARGE_INTEGER windows_file_size = {}; + if (!GetFileSizeEx(windows_file, &windows_file_size) || + static_cast<ULONGLONG>(windows_file_size.QuadPart) > + std::numeric_limits<size_t>::max()) { + UnmapViewOfFile(data); + data = NULL; + return; + } + size = static_cast<size_t>(windows_file_size.QuadPart); +#elif defined(TINYEXR_USE_POSIX_MMAP) + posix_descriptor = open(filename, O_RDONLY); + if (posix_descriptor == -1) { + return; + } + + struct stat info; + if (fstat(posix_descriptor, &info) < 0) { + return; + } + // Make sure st_size is in the valid range for a size_t. The second case + // can only fail if a POSIX implementation defines off_t to be a larger + // type than size_t - for instance, compiling with _FILE_OFFSET_BITS=64 + // on a 32-bit system. On current 64-bit systems, this check can never + // fail, so we turn off clang's Wtautological-type-limit-compare warning + // around this code. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-type-limit-compare" +#endif + if (info.st_size < 0 || + info.st_size > std::numeric_limits<ssize_t>::max()) { + return; + } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + size = static_cast<size_t>(info.st_size); + + data = reinterpret_cast<unsigned char *>( + mmap(0, size, PROT_READ, MAP_SHARED, posix_descriptor, 0)); + if (data == MAP_FAILED) { + data = nullptr; + return; + } +#else + FILE *fp = fopen(filename, "rb"); + if (!fp) { + return; + } + + // Calling fseek(fp, 0, SEEK_END) isn't strictly-conforming C code, but + // since neither the WIN32 nor POSIX APIs are available in this branch, this + // is a reasonable fallback option. + if (fseek(fp, 0, SEEK_END) != 0) { + fclose(fp); + return; + } + const long ftell_result = ftell(fp); + if (ftell_result < 0) { + // Error from ftell + fclose(fp); + return; + } + size = static_cast<size_t>(ftell_result); + if (fseek(fp, 0, SEEK_SET) != 0) { + fclose(fp); + size = 0; + return; + } + + data = reinterpret_cast<unsigned char *>(malloc(size)); + if (!data) { + size = 0; + fclose(fp); + return; + } + size_t read_bytes = fread(data, 1, size, fp); + if (read_bytes != size) { + // TODO: Try to read data until reading `size` bytes. + fclose(fp); + size = 0; + data = nullptr; + return; + } + fclose(fp); +#endif + } + + // MemoryMappedFile's destructor closes all its handles. + ~MemoryMappedFile() { +#ifdef TINYEXR_USE_WIN32_MMAP + if (data) { + (void)UnmapViewOfFile(data); + data = NULL; + } + + if (windows_file_mapping != NULL) { + (void)CloseHandle(windows_file_mapping); + } + + if (windows_file != INVALID_HANDLE_VALUE) { + (void)CloseHandle(windows_file); + } +#elif defined(TINYEXR_USE_POSIX_MMAP) + if (data) { + (void)munmap(data, size); + data = NULL; + } + + if (posix_descriptor != -1) { + (void)close(posix_descriptor); + } +#else + if (data) { + (void)free(data); + } + data = NULL; +#endif + } + + // A MemoryMappedFile cannot be copied or moved. + // Only check for this when compiling with C++11 or higher, since deleted + // function definitions were added then. +#if TINYEXR_HAS_CXX11 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + MemoryMappedFile(const MemoryMappedFile &) = delete; + MemoryMappedFile &operator=(const MemoryMappedFile &) = delete; + MemoryMappedFile(MemoryMappedFile &&other) noexcept = delete; + MemoryMappedFile &operator=(MemoryMappedFile &&other) noexcept = delete; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif + + // Returns whether this was successfully opened. + bool valid() const { return data; } +}; + +int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header, + const char *filename, const char **err) { + if (exr_image == NULL) { + tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromFile", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + MemoryMappedFile file(filename); + if (!file.valid()) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } + + if (file.size < 16) { + tinyexr::SetErrorMessage("File size too short : " + std::string(filename), + err); + return TINYEXR_ERROR_INVALID_FILE; + } + + return LoadEXRImageFromMemory(exr_image, exr_header, file.data, file.size, + err); +} + +int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header, + const unsigned char *memory, const size_t size, + const char **err) { + if (exr_image == NULL || memory == NULL || + (size < tinyexr::kEXRVersionSize)) { + tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory", + err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if (exr_header->header_len == 0) { + tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + const unsigned char *head = memory; + const unsigned char *marker = reinterpret_cast<const unsigned char *>( + memory + exr_header->header_len + + 8); // +8 for magic number + version header. + return tinyexr::DecodeEXRImage(exr_image, exr_header, head, marker, size, + err); +} + +namespace tinyexr +{ + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-conversion" +#endif + +// out_data must be allocated initially with the block-header size +// of the current image(-part) type +static bool EncodePixelData(/* out */ std::vector<unsigned char>& out_data, + const unsigned char* const* images, + int compression_type, + int /*line_order*/, + int width, // for tiled : tile.width + int /*height*/, // for tiled : header.tile_size_y + int x_stride, // for tiled : header.tile_size_x + int line_no, // for tiled : 0 + int num_lines, // for tiled : tile.height + size_t pixel_data_size, + const std::vector<ChannelInfo>& channels, + const std::vector<size_t>& channel_offset_list, + std::string *err, + const void* compression_param = 0) // zfp compression param +{ + size_t buf_size = static_cast<size_t>(width) * + static_cast<size_t>(num_lines) * + static_cast<size_t>(pixel_data_size); + //int last2bit = (buf_size & 3); + // buf_size must be multiple of four + //if(last2bit) buf_size += 4 - last2bit; + std::vector<unsigned char> buf(buf_size); + + size_t start_y = static_cast<size_t>(line_no); + for (size_t c = 0; c < channels.size(); c++) { + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + for (int y = 0; y < num_lines; y++) { + // Assume increasing Y + float *line_ptr = reinterpret_cast<float *>(&buf.at( + static_cast<size_t>(pixel_data_size * size_t(y) * size_t(width)) + + channel_offset_list[c] * + static_cast<size_t>(width))); + for (int x = 0; x < width; x++) { + tinyexr::FP16 h16; + h16.u = reinterpret_cast<const unsigned short * const *>( + images)[c][(y + start_y) * size_t(x_stride) + size_t(x)]; + + tinyexr::FP32 f32 = half_to_float(h16); + + tinyexr::swap4(&f32.f); + + // line_ptr[x] = f32.f; + tinyexr::cpy4(line_ptr + x, &(f32.f)); + } + } + } else if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) { + for (int y = 0; y < num_lines; y++) { + // Assume increasing Y + unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &buf.at(static_cast<size_t>(pixel_data_size * y * + width) + + channel_offset_list[c] * + static_cast<size_t>(width))); + for (int x = 0; x < width; x++) { + unsigned short val = reinterpret_cast<const unsigned short * const *>( + images)[c][(y + start_y) * x_stride + x]; + + tinyexr::swap2(&val); + + // line_ptr[x] = val; + tinyexr::cpy2(line_ptr + x, &val); + } + } + } else { + if (err) { + (*err) += "Invalid requested_pixel_type.\n"; + } + return false; + } + + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) { + for (int y = 0; y < num_lines; y++) { + // Assume increasing Y + unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &buf.at(static_cast<size_t>(pixel_data_size * y * + width) + + channel_offset_list[c] * + static_cast<size_t>(width))); + for (int x = 0; x < width; x++) { + tinyexr::FP32 f32; + f32.f = reinterpret_cast<const float * const *>( + images)[c][(y + start_y) * x_stride + x]; + + tinyexr::FP16 h16; + h16 = float_to_half_full(f32); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&h16.u)); + + // line_ptr[x] = h16.u; + tinyexr::cpy2(line_ptr + x, &(h16.u)); + } + } + } else if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + for (int y = 0; y < num_lines; y++) { + // Assume increasing Y + float *line_ptr = reinterpret_cast<float *>(&buf.at( + static_cast<size_t>(pixel_data_size * y * width) + + channel_offset_list[c] * + static_cast<size_t>(width))); + for (int x = 0; x < width; x++) { + float val = reinterpret_cast<const float * const *>( + images)[c][(y + start_y) * x_stride + x]; + + tinyexr::swap4(&val); + + // line_ptr[x] = val; + tinyexr::cpy4(line_ptr + x, &val); + } + } + } else { + if (err) { + (*err) += "Invalid requested_pixel_type.\n"; + } + return false; + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + for (int y = 0; y < num_lines; y++) { + // Assume increasing Y + unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at( + static_cast<size_t>(pixel_data_size * y * width) + + channel_offset_list[c] * static_cast<size_t>(width))); + for (int x = 0; x < width; x++) { + unsigned int val = reinterpret_cast<const unsigned int * const *>( + images)[c][(y + start_y) * x_stride + x]; + + tinyexr::swap4(&val); + + // line_ptr[x] = val; + tinyexr::cpy4(line_ptr + x, &val); + } + } + } + } + + if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) { + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(uncompressed) + out_data.insert(out_data.end(), buf.begin(), buf.end()); + + } else if ((compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) || + (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) { +#if TINYEXR_USE_MINIZ + std::vector<unsigned char> block(mz_compressBound( + static_cast<unsigned long>(buf.size()))); +#elif TINYEXR_USE_STB_ZLIB + // there is no compressBound() function, so we use a value that + // is grossly overestimated, but should always work + std::vector<unsigned char> block(256 + 2 * buf.size()); +#else + std::vector<unsigned char> block( + compressBound(static_cast<uLong>(buf.size()))); +#endif + tinyexr::tinyexr_uint64 outSize = block.size(); + + if (!tinyexr::CompressZip(&block.at(0), outSize, + reinterpret_cast<const unsigned char *>(&buf.at(0)), + static_cast<unsigned long>(buf.size()))) { + if (err) { + (*err) += "Zip compresssion failed.\n"; + } + return false; + } + + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(compressed) + unsigned int data_len = static_cast<unsigned int>(outSize); // truncate + + out_data.insert(out_data.end(), block.begin(), block.begin() + data_len); + + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) { + // (buf.size() * 3) / 2 would be enough. + std::vector<unsigned char> block((buf.size() * 3) / 2); + + tinyexr::tinyexr_uint64 outSize = block.size(); + + if (!tinyexr::CompressRle(&block.at(0), outSize, + reinterpret_cast<const unsigned char *>(&buf.at(0)), + static_cast<unsigned long>(buf.size()))) { + if (err) { + (*err) += "RLE compresssion failed.\n"; + } + return false; + } + + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(compressed) + unsigned int data_len = static_cast<unsigned int>(outSize); // truncate + out_data.insert(out_data.end(), block.begin(), block.begin() + data_len); + + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { +#if TINYEXR_USE_PIZ + unsigned int bufLen = + 8192 + static_cast<unsigned int>( + 2 * static_cast<unsigned int>( + buf.size())); // @fixme { compute good bound. } + std::vector<unsigned char> block(bufLen); + unsigned int outSize = static_cast<unsigned int>(block.size()); + + if (!CompressPiz(&block.at(0), &outSize, + reinterpret_cast<const unsigned char *>(&buf.at(0)), + buf.size(), channels, width, num_lines)) { + if (err) { + (*err) += "PIZ compresssion failed.\n"; + } + return false; + } + + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(compressed) + unsigned int data_len = outSize; + out_data.insert(out_data.end(), block.begin(), block.begin() + data_len); + +#else + if (err) { + (*err) += "PIZ compression is disabled in this build.\n"; + } + return false; +#endif + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { +#if TINYEXR_USE_ZFP + const ZFPCompressionParam* zfp_compression_param = reinterpret_cast<const ZFPCompressionParam*>(compression_param); + std::vector<unsigned char> block; + unsigned int outSize; + + tinyexr::CompressZfp( + &block, &outSize, reinterpret_cast<const float *>(&buf.at(0)), + width, num_lines, static_cast<int>(channels.size()), *zfp_compression_param); + + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(compressed) + unsigned int data_len = outSize; + out_data.insert(out_data.end(), block.begin(), block.begin() + data_len); + +#else + if (err) { + (*err) += "ZFP compression is disabled in this build.\n"; + } + (void)compression_param; + return false; +#endif + } else { + return false; + } + + return true; +} + +static int EncodeTiledLevel(const EXRImage* level_image, const EXRHeader* exr_header, + const std::vector<tinyexr::ChannelInfo>& channels, + std::vector<std::vector<unsigned char> >& data_list, + size_t start_index, // for data_list + int num_x_tiles, int num_y_tiles, + const std::vector<size_t>& channel_offset_list, + int pixel_data_size, + const void* compression_param, // must be set if zfp compression is enabled + std::string* err) { + int num_tiles = num_x_tiles * num_y_tiles; + if (num_tiles != level_image->num_tiles) { + if (err) { + (*err) += "Invalid number of tiles in argument.\n"; + } + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if ((exr_header->tile_size_x > level_image->width || exr_header->tile_size_y > level_image->height) && + level_image->level_x == 0 && level_image->level_y == 0) { + if (err) { + (*err) += "Failed to encode tile data.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::atomic<bool> invalid_data(false); +#else + bool invalid_data(false); +#endif + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::vector<std::thread> workers; + std::atomic<int> tile_count(0); + + int num_threads = std::max(1, int(std::thread::hardware_concurrency())); + if (num_threads > int(num_tiles)) { + num_threads = int(num_tiles); + } + + for (int t = 0; t < num_threads; t++) { + workers.emplace_back(std::thread([&]() { + int i = 0; + while ((i = tile_count++) < num_tiles) { + +#else + // Use signed int since some OpenMP compiler doesn't allow unsigned type for + // `parallel for` +#if TINYEXR_USE_OPENMP +#pragma omp parallel for +#endif + for (int i = 0; i < num_tiles; i++) { + +#endif + size_t tile_idx = static_cast<size_t>(i); + size_t data_idx = tile_idx + start_index; + + int x_tile = i % num_x_tiles; + int y_tile = i / num_x_tiles; + + EXRTile& tile = level_image->tiles[tile_idx]; + + const unsigned char* const* images = + static_cast<const unsigned char* const*>(tile.images); + + data_list[data_idx].resize(5*sizeof(int)); + size_t data_header_size = data_list[data_idx].size(); + bool ret = EncodePixelData(data_list[data_idx], + images, + exr_header->compression_type, + 0, // increasing y + tile.width, + exr_header->tile_size_y, + exr_header->tile_size_x, + 0, + tile.height, + pixel_data_size, + channels, + channel_offset_list, + err, compression_param); + if (!ret) { + invalid_data = true; + continue; + } + if (data_list[data_idx].size() <= data_header_size) { + invalid_data = true; + continue; + } + + int data_len = static_cast<int>(data_list[data_idx].size() - data_header_size); + //tileX, tileY, levelX, levelY // pixel_data_size(int) + memcpy(&data_list[data_idx][0], &x_tile, sizeof(int)); + memcpy(&data_list[data_idx][4], &y_tile, sizeof(int)); + memcpy(&data_list[data_idx][8], &level_image->level_x, sizeof(int)); + memcpy(&data_list[data_idx][12], &level_image->level_y, sizeof(int)); + memcpy(&data_list[data_idx][16], &data_len, sizeof(int)); + + swap4(reinterpret_cast<int*>(&data_list[data_idx][0])); + swap4(reinterpret_cast<int*>(&data_list[data_idx][4])); + swap4(reinterpret_cast<int*>(&data_list[data_idx][8])); + swap4(reinterpret_cast<int*>(&data_list[data_idx][12])); + swap4(reinterpret_cast<int*>(&data_list[data_idx][16])); + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + } +})); + } + + for (auto &t : workers) { + t.join(); + } +#else + } // omp parallel +#endif + + if (invalid_data) { + if (err) { + (*err) += "Failed to encode tile data.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + return TINYEXR_SUCCESS; +} + +static int NumScanlines(int compression_type) { + int num_scanlines = 1; + if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) { + num_scanlines = 16; + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { + num_scanlines = 32; + } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { + num_scanlines = 16; + } + return num_scanlines; +} + +static int EncodeChunk(const EXRImage* exr_image, const EXRHeader* exr_header, + const std::vector<ChannelInfo>& channels, + int num_blocks, + tinyexr_uint64 chunk_offset, // starting offset of current chunk + bool is_multipart, + OffsetData& offset_data, // output block offsets, must be initialized + std::vector<std::vector<unsigned char> >& data_list, // output + tinyexr_uint64& total_size, // output: ending offset of current chunk + std::string* err) { + int num_scanlines = NumScanlines(exr_header->compression_type); + + data_list.resize(num_blocks); + + std::vector<size_t> channel_offset_list( + static_cast<size_t>(exr_header->num_channels)); + + int pixel_data_size = 0; + { + size_t channel_offset = 0; + for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) { + channel_offset_list[c] = channel_offset; + if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) { + pixel_data_size += sizeof(unsigned short); + channel_offset += sizeof(unsigned short); + } else if (channels[c].requested_pixel_type == + TINYEXR_PIXELTYPE_FLOAT) { + pixel_data_size += sizeof(float); + channel_offset += sizeof(float); + } else if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_UINT) { + pixel_data_size += sizeof(unsigned int); + channel_offset += sizeof(unsigned int); + } else { + if (err) { + (*err) += "Invalid requested_pixel_type.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + } + } + + const void* compression_param = 0; +#if TINYEXR_USE_ZFP + tinyexr::ZFPCompressionParam zfp_compression_param; + + // Use ZFP compression parameter from custom attributes(if such a parameter + // exists) + { + std::string e; + bool ret = tinyexr::FindZFPCompressionParam( + &zfp_compression_param, exr_header->custom_attributes, + exr_header->num_custom_attributes, &e); + + if (!ret) { + // Use predefined compression parameter. + zfp_compression_param.type = 0; + zfp_compression_param.rate = 2; + } + compression_param = &zfp_compression_param; + } +#endif + + tinyexr_uint64 offset = chunk_offset; + tinyexr_uint64 doffset = is_multipart ? 4u : 0u; + + if (exr_image->tiles) { + const EXRImage* level_image = exr_image; + size_t block_idx = 0; + //tinyexr::tinyexr_uint64 block_data_size = 0; + int num_levels = (exr_header->tile_level_mode != TINYEXR_TILE_RIPMAP_LEVELS) ? + offset_data.num_x_levels : (offset_data.num_x_levels * offset_data.num_y_levels); + for (int level_index = 0; level_index < num_levels; ++level_index) { + if (!level_image) { + if (err) { + (*err) += "Invalid number of tiled levels for EncodeChunk\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + int level_index_from_image = LevelIndex(level_image->level_x, level_image->level_y, + exr_header->tile_level_mode, offset_data.num_x_levels); + if (level_index_from_image < 0) { + if (err) { + (*err) += "Invalid tile level mode\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + if (level_index_from_image != level_index) { + if (err) { + (*err) += "Incorrect level ordering in tiled image\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + int num_y_tiles = int(offset_data.offsets[level_index].size()); + if (num_y_tiles <= 0) { + if (err) { + (*err) += "Invalid Y tile size\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + int num_x_tiles = int(offset_data.offsets[level_index][0].size()); + if (num_x_tiles <= 0) { + if (err) { + (*err) += "Invalid X tile size\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + std::string e; + int ret = EncodeTiledLevel(level_image, + exr_header, + channels, + data_list, + block_idx, + num_x_tiles, + num_y_tiles, + channel_offset_list, + pixel_data_size, + compression_param, + &e); + if (ret != TINYEXR_SUCCESS) { + if (!e.empty() && err) { + (*err) += e; + } + return ret; + } + + for (size_t j = 0; j < static_cast<size_t>(num_y_tiles); ++j) + for (size_t i = 0; i < static_cast<size_t>(num_x_tiles); ++i) { + offset_data.offsets[level_index][j][i] = offset; + swap8(reinterpret_cast<tinyexr_uint64*>(&offset_data.offsets[level_index][j][i])); + offset += data_list[block_idx].size() + doffset; + //block_data_size += data_list[block_idx].size(); + ++block_idx; + } + level_image = level_image->next_level; + } + TINYEXR_CHECK_AND_RETURN_C(static_cast<int>(block_idx) == num_blocks, TINYEXR_ERROR_INVALID_DATA); + total_size = offset; + } else { // scanlines + std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data.offsets[0][0]; + +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + std::atomic<bool> invalid_data(false); + std::vector<std::thread> workers; + std::atomic<int> block_count(0); + + int num_threads = std::min(std::max(1, int(std::thread::hardware_concurrency())), num_blocks); + + for (int t = 0; t < num_threads; t++) { + workers.emplace_back(std::thread([&]() { + int i = 0; + while ((i = block_count++) < num_blocks) { + +#else + bool invalid_data(false); +#if TINYEXR_USE_OPENMP +#pragma omp parallel for +#endif + for (int i = 0; i < num_blocks; i++) { + +#endif + int start_y = num_scanlines * i; + int end_Y = (std::min)(num_scanlines * (i + 1), exr_image->height); + int num_lines = end_Y - start_y; + + const unsigned char* const* images = + static_cast<const unsigned char* const*>(exr_image->images); + + data_list[i].resize(2*sizeof(int)); + size_t data_header_size = data_list[i].size(); + + bool ret = EncodePixelData(data_list[i], + images, + exr_header->compression_type, + 0, // increasing y + exr_image->width, + exr_image->height, + exr_image->width, + start_y, + num_lines, + pixel_data_size, + channels, + channel_offset_list, + err, + compression_param); + if (!ret) { + invalid_data = true; + continue; // "break" cannot be used with OpenMP + } + if (data_list[i].size() <= data_header_size) { + invalid_data = true; + continue; // "break" cannot be used with OpenMP + } + int data_len = static_cast<int>(data_list[i].size() - data_header_size); + memcpy(&data_list[i][0], &start_y, sizeof(int)); + memcpy(&data_list[i][4], &data_len, sizeof(int)); + + swap4(reinterpret_cast<int*>(&data_list[i][0])); + swap4(reinterpret_cast<int*>(&data_list[i][4])); +#if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) + } + })); + } + + for (auto &t : workers) { + t.join(); + } +#else + } // omp parallel +#endif + + if (invalid_data) { + if (err) { + (*err) += "Failed to encode scanline data.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } + + for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) { + offsets[i] = offset; + tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offsets[i])); + offset += data_list[i].size() + doffset; + } + + total_size = static_cast<size_t>(offset); + } + return TINYEXR_SUCCESS; +} + +// can save a single or multi-part image (no deep* formats) +static size_t SaveEXRNPartImageToMemory(const EXRImage* exr_images, + const EXRHeader** exr_headers, + unsigned int num_parts, + unsigned char** memory_out, const char** err) { + if (exr_images == NULL || exr_headers == NULL || num_parts == 0 || + memory_out == NULL) { + SetErrorMessage("Invalid argument for SaveEXRNPartImageToMemory", + err); + return 0; + } + { + for (unsigned int i = 0; i < num_parts; ++i) { + if (exr_headers[i]->compression_type < 0) { + SetErrorMessage("Invalid argument for SaveEXRNPartImageToMemory", + err); + return 0; + } +#if !TINYEXR_USE_PIZ + if (exr_headers[i]->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { + SetErrorMessage("PIZ compression is not supported in this build", + err); + return 0; + } +#endif +#if !TINYEXR_USE_ZFP + if (exr_headers[i]->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { + SetErrorMessage("ZFP compression is not supported in this build", + err); + return 0; + } +#else + for (int c = 0; c < exr_header->num_channels; ++c) { + if (exr_headers[i]->requested_pixel_types[c] != TINYEXR_PIXELTYPE_FLOAT) { + SetErrorMessage("Pixel type must be FLOAT for ZFP compression", + err); + return 0; + } + } +#endif + } + } + + std::vector<unsigned char> memory; + + // Header + { + const char header[] = { 0x76, 0x2f, 0x31, 0x01 }; + memory.insert(memory.end(), header, header + 4); + } + + // Version + // using value from the first header + int long_name = exr_headers[0]->long_name; + { + char marker[] = { 2, 0, 0, 0 }; + /* @todo + if (exr_header->non_image) { + marker[1] |= 0x8; + } + */ + // tiled + if (num_parts == 1 && exr_images[0].tiles) { + marker[1] |= 0x2; + } + // long_name + if (long_name) { + marker[1] |= 0x4; + } + // multipart + if (num_parts > 1) { + marker[1] |= 0x10; + } + memory.insert(memory.end(), marker, marker + 4); + } + + int total_chunk_count = 0; + std::vector<int> chunk_count(num_parts); + std::vector<OffsetData> offset_data(num_parts); + for (unsigned int i = 0; i < num_parts; ++i) { + if (!exr_images[i].tiles) { + int num_scanlines = NumScanlines(exr_headers[i]->compression_type); + chunk_count[i] = + (exr_images[i].height + num_scanlines - 1) / num_scanlines; + InitSingleResolutionOffsets(offset_data[i], chunk_count[i]); + total_chunk_count += chunk_count[i]; + } else { + { + std::vector<int> num_x_tiles, num_y_tiles; + if (!PrecalculateTileInfo(num_x_tiles, num_y_tiles, exr_headers[i])) { + SetErrorMessage("Failed to precalculate Tile info", + err); + return TINYEXR_ERROR_INVALID_DATA; + } + int ntiles = InitTileOffsets(offset_data[i], exr_headers[i], num_x_tiles, num_y_tiles); + if (ntiles > 0) { + chunk_count[i] = ntiles; + } else { + SetErrorMessage("Failed to compute Tile offsets", + err); + return TINYEXR_ERROR_INVALID_DATA; + + } + total_chunk_count += chunk_count[i]; + } + } + } + // Write attributes to memory buffer. + std::vector< std::vector<tinyexr::ChannelInfo> > channels(num_parts); + { + std::set<std::string> partnames; + for (unsigned int i = 0; i < num_parts; ++i) { + //channels + { + std::vector<unsigned char> data; + + for (int c = 0; c < exr_headers[i]->num_channels; c++) { + tinyexr::ChannelInfo info; + info.p_linear = 0; + info.pixel_type = exr_headers[i]->pixel_types[c]; + info.requested_pixel_type = exr_headers[i]->requested_pixel_types[c]; + info.x_sampling = 1; + info.y_sampling = 1; + info.name = std::string(exr_headers[i]->channels[c].name); + channels[i].push_back(info); + } + + tinyexr::WriteChannelInfo(data, channels[i]); + + tinyexr::WriteAttributeToMemory(&memory, "channels", "chlist", &data.at(0), + static_cast<int>(data.size())); + } + + { + int comp = exr_headers[i]->compression_type; + swap4(&comp); + WriteAttributeToMemory( + &memory, "compression", "compression", + reinterpret_cast<const unsigned char*>(&comp), 1); + } + + { + int data[4] = { 0, 0, exr_images[i].width - 1, exr_images[i].height - 1 }; + swap4(&data[0]); + swap4(&data[1]); + swap4(&data[2]); + swap4(&data[3]); + WriteAttributeToMemory( + &memory, "dataWindow", "box2i", + reinterpret_cast<const unsigned char*>(data), sizeof(int) * 4); + + int data0[4] = { 0, 0, exr_images[0].width - 1, exr_images[0].height - 1 }; + swap4(&data0[0]); + swap4(&data0[1]); + swap4(&data0[2]); + swap4(&data0[3]); + // Note: must be the same across parts (currently, using value from the first header) + WriteAttributeToMemory( + &memory, "displayWindow", "box2i", + reinterpret_cast<const unsigned char*>(data0), sizeof(int) * 4); + } + + { + unsigned char line_order = 0; // @fixme { read line_order from EXRHeader } + WriteAttributeToMemory(&memory, "lineOrder", "lineOrder", + &line_order, 1); + } + + { + // Note: must be the same across parts + float aspectRatio = 1.0f; + swap4(&aspectRatio); + WriteAttributeToMemory( + &memory, "pixelAspectRatio", "float", + reinterpret_cast<const unsigned char*>(&aspectRatio), sizeof(float)); + } + + { + float center[2] = { 0.0f, 0.0f }; + swap4(¢er[0]); + swap4(¢er[1]); + WriteAttributeToMemory( + &memory, "screenWindowCenter", "v2f", + reinterpret_cast<const unsigned char*>(center), 2 * sizeof(float)); + } + + { + float w = 1.0f; + swap4(&w); + WriteAttributeToMemory(&memory, "screenWindowWidth", "float", + reinterpret_cast<const unsigned char*>(&w), + sizeof(float)); + } + + if (exr_images[i].tiles) { + unsigned char tile_mode = static_cast<unsigned char>(exr_headers[i]->tile_level_mode & 0x3); + if (exr_headers[i]->tile_rounding_mode) tile_mode |= (1u << 4u); + //unsigned char data[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + unsigned int datai[3] = { 0, 0, 0 }; + unsigned char* data = reinterpret_cast<unsigned char*>(&datai[0]); + datai[0] = static_cast<unsigned int>(exr_headers[i]->tile_size_x); + datai[1] = static_cast<unsigned int>(exr_headers[i]->tile_size_y); + data[8] = tile_mode; + swap4(reinterpret_cast<unsigned int*>(&data[0])); + swap4(reinterpret_cast<unsigned int*>(&data[4])); + WriteAttributeToMemory( + &memory, "tiles", "tiledesc", + reinterpret_cast<const unsigned char*>(data), 9); + } + + // must be present for multi-part files - according to spec. + if (num_parts > 1) { + // name + { + size_t len = 0; + if ((len = strlen(exr_headers[i]->name)) > 0) { +#if TINYEXR_HAS_CXX11 + partnames.emplace(exr_headers[i]->name); +#else + partnames.insert(std::string(exr_headers[i]->name)); +#endif + if (partnames.size() != i + 1) { + SetErrorMessage("'name' attributes must be unique for a multi-part file", err); + return 0; + } + WriteAttributeToMemory( + &memory, "name", "string", + reinterpret_cast<const unsigned char*>(exr_headers[i]->name), + static_cast<int>(len)); + } else { + SetErrorMessage("Invalid 'name' attribute for a multi-part file", err); + return 0; + } + } + // type + { + const char* type = "scanlineimage"; + if (exr_images[i].tiles) type = "tiledimage"; + WriteAttributeToMemory( + &memory, "type", "string", + reinterpret_cast<const unsigned char*>(type), + static_cast<int>(strlen(type))); + } + // chunkCount + { + WriteAttributeToMemory( + &memory, "chunkCount", "int", + reinterpret_cast<const unsigned char*>(&chunk_count[i]), + 4); + } + } + + // Custom attributes + if (exr_headers[i]->num_custom_attributes > 0) { + for (int j = 0; j < exr_headers[i]->num_custom_attributes; j++) { + tinyexr::WriteAttributeToMemory( + &memory, exr_headers[i]->custom_attributes[j].name, + exr_headers[i]->custom_attributes[j].type, + reinterpret_cast<const unsigned char*>( + exr_headers[i]->custom_attributes[j].value), + exr_headers[i]->custom_attributes[j].size); + } + } + + { // end of header + memory.push_back(0); + } + } + } + if (num_parts > 1) { + // end of header list + memory.push_back(0); + } + + tinyexr_uint64 chunk_offset = memory.size() + size_t(total_chunk_count) * sizeof(tinyexr_uint64); + + tinyexr_uint64 total_size = 0; + std::vector< std::vector< std::vector<unsigned char> > > data_lists(num_parts); + for (unsigned int i = 0; i < num_parts; ++i) { + std::string e; + int ret = EncodeChunk(&exr_images[i], exr_headers[i], + channels[i], + chunk_count[i], + // starting offset of current chunk after part-number + chunk_offset, + num_parts > 1, + offset_data[i], // output: block offsets, must be initialized + data_lists[i], // output + total_size, // output + &e); + if (ret != TINYEXR_SUCCESS) { + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } + return 0; + } + chunk_offset = total_size; + } + + // Allocating required memory + if (total_size == 0) { // something went wrong + tinyexr::SetErrorMessage("Output memory size is zero", err); + return TINYEXR_ERROR_INVALID_DATA; + } + (*memory_out) = static_cast<unsigned char*>(malloc(size_t(total_size))); + + // Writing header + memcpy((*memory_out), &memory[0], memory.size()); + unsigned char* memory_ptr = *memory_out + memory.size(); + size_t sum = memory.size(); + + // Writing offset data for chunks + for (unsigned int i = 0; i < num_parts; ++i) { + if (exr_images[i].tiles) { + const EXRImage* level_image = &exr_images[i]; + int num_levels = (exr_headers[i]->tile_level_mode != TINYEXR_TILE_RIPMAP_LEVELS) ? + offset_data[i].num_x_levels : (offset_data[i].num_x_levels * offset_data[i].num_y_levels); + for (int level_index = 0; level_index < num_levels; ++level_index) { + for (size_t j = 0; j < offset_data[i].offsets[level_index].size(); ++j) { + size_t num_bytes = sizeof(tinyexr_uint64) * offset_data[i].offsets[level_index][j].size(); + sum += num_bytes; + if (sum > total_size) { + tinyexr::SetErrorMessage("Invalid offset bytes in Tiled Part image.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + memcpy(memory_ptr, + reinterpret_cast<unsigned char*>(&offset_data[i].offsets[level_index][j][0]), + num_bytes); + memory_ptr += num_bytes; + } + level_image = level_image->next_level; + } + } else { + size_t num_bytes = sizeof(tinyexr::tinyexr_uint64) * static_cast<size_t>(chunk_count[i]); + sum += num_bytes; + if (sum > total_size) { + tinyexr::SetErrorMessage("Invalid offset bytes in Part image.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data[i].offsets[0][0]; + memcpy(memory_ptr, reinterpret_cast<unsigned char*>(&offsets[0]), num_bytes); + memory_ptr += num_bytes; + } + } + + // Writing chunk data + for (unsigned int i = 0; i < num_parts; ++i) { + for (size_t j = 0; j < static_cast<size_t>(chunk_count[i]); ++j) { + if (num_parts > 1) { + sum += 4; + if (sum > total_size) { + tinyexr::SetErrorMessage("Buffer overrun in reading Part image chunk data.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + unsigned int part_number = i; + swap4(&part_number); + memcpy(memory_ptr, &part_number, 4); + memory_ptr += 4; + } + sum += data_lists[i][j].size(); + if (sum > total_size) { + tinyexr::SetErrorMessage("Buffer overrun in reading Part image chunk data.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + memcpy(memory_ptr, &data_lists[i][j][0], data_lists[i][j].size()); + memory_ptr += data_lists[i][j].size(); + } + } + + if (sum != total_size) { + tinyexr::SetErrorMessage("Corrupted Part image chunk data.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + return size_t(total_size); // OK +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +} // tinyexr + +size_t SaveEXRImageToMemory(const EXRImage* exr_image, + const EXRHeader* exr_header, + unsigned char** memory_out, const char** err) { + return tinyexr::SaveEXRNPartImageToMemory(exr_image, &exr_header, 1, memory_out, err); +} + +int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header, + const char *filename, const char **err) { + if (exr_image == NULL || filename == NULL || + exr_header->compression_type < 0) { + tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToFile", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + +#if !TINYEXR_USE_PIZ + if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { + tinyexr::SetErrorMessage("PIZ compression is not supported in this build", + err); + return TINYEXR_ERROR_UNSUPPORTED_FEATURE; + } +#endif + +#if !TINYEXR_USE_ZFP + if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { + tinyexr::SetErrorMessage("ZFP compression is not supported in this build", + err); + return TINYEXR_ERROR_UNSUPPORTED_FEATURE; + } +#endif + + FILE *fp = NULL; +#ifdef _WIN32 +#if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) // MSVC, MinGW GCC, or Clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"wb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename), + err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } +#else + // Unknown compiler or MinGW without MINGW_HAS_SECURE_API. + fp = fopen(filename, "wb"); +#endif +#else + fp = fopen(filename, "wb"); +#endif + if (!fp) { + tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename), + err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } + + unsigned char *mem = NULL; + size_t mem_size = SaveEXRImageToMemory(exr_image, exr_header, &mem, err); + if (mem_size == 0) { + fclose(fp); + return TINYEXR_ERROR_SERIALIZATION_FAILED; + } + + size_t written_size = 0; + if ((mem_size > 0) && mem) { + written_size = fwrite(mem, 1, mem_size, fp); + } + free(mem); + + fclose(fp); + + if (written_size != mem_size) { + tinyexr::SetErrorMessage("Cannot write a file", err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } + + return TINYEXR_SUCCESS; +} + +size_t SaveEXRMultipartImageToMemory(const EXRImage* exr_images, + const EXRHeader** exr_headers, + unsigned int num_parts, + unsigned char** memory_out, const char** err) { + if (exr_images == NULL || exr_headers == NULL || num_parts < 2 || + memory_out == NULL) { + tinyexr::SetErrorMessage("Invalid argument for SaveEXRNPartImageToMemory", + err); + return 0; + } + return tinyexr::SaveEXRNPartImageToMemory(exr_images, exr_headers, num_parts, memory_out, err); +} + +int SaveEXRMultipartImageToFile(const EXRImage* exr_images, + const EXRHeader** exr_headers, + unsigned int num_parts, + const char* filename, + const char** err) { + if (exr_images == NULL || exr_headers == NULL || num_parts < 2) { + tinyexr::SetErrorMessage("Invalid argument for SaveEXRMultipartImageToFile", + err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + FILE *fp = NULL; +#ifdef _WIN32 +#if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) // MSVC, MinGW GCC, or Clang. + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"wb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename), + err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } +#else + // Unknown compiler or MinGW without MINGW_HAS_SECURE_API. + fp = fopen(filename, "wb"); +#endif +#else + fp = fopen(filename, "wb"); +#endif + if (!fp) { + tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename), + err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } + + unsigned char *mem = NULL; + size_t mem_size = SaveEXRMultipartImageToMemory(exr_images, exr_headers, num_parts, &mem, err); + if (mem_size == 0) { + fclose(fp); + return TINYEXR_ERROR_SERIALIZATION_FAILED; + } + + size_t written_size = 0; + if ((mem_size > 0) && mem) { + written_size = fwrite(mem, 1, mem_size, fp); + } + free(mem); + + fclose(fp); + + if (written_size != mem_size) { + tinyexr::SetErrorMessage("Cannot write a file", err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } + + return TINYEXR_SUCCESS; +} + +int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { + if (deep_image == NULL) { + tinyexr::SetErrorMessage("Invalid argument for LoadDeepEXR", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + MemoryMappedFile file(filename); + if (!file.valid()) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } + + if (file.size == 0) { + tinyexr::SetErrorMessage("File size is zero : " + std::string(filename), + err); + return TINYEXR_ERROR_INVALID_FILE; + } + + const char *head = reinterpret_cast<const char *>(file.data); + const char *marker = reinterpret_cast<const char *>(file.data); + + // Header check. + { + const char header[] = {0x76, 0x2f, 0x31, 0x01}; + + if (memcmp(marker, header, 4) != 0) { + tinyexr::SetErrorMessage("Invalid magic number", err); + return TINYEXR_ERROR_INVALID_MAGIC_NUMBER; + } + marker += 4; + } + + // Version, scanline. + { + // ver 2.0, scanline, deep bit on(0x800) + // must be [2, 0, 0, 0] + if (marker[0] != 2 || marker[1] != 8 || marker[2] != 0 || marker[3] != 0) { + tinyexr::SetErrorMessage("Unsupported version or scanline", err); + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; + } + + marker += 4; + } + + int dx = -1; + int dy = -1; + int dw = -1; + int dh = -1; + int num_scanline_blocks = 1; // 16 for ZIP compression. + int compression_type = -1; + int num_channels = -1; + std::vector<tinyexr::ChannelInfo> channels; + + // Read attributes + size_t size = file.size - tinyexr::kEXRVersionSize; + for (;;) { + if (0 == size) { + return TINYEXR_ERROR_INVALID_DATA; + } else if (marker[0] == '\0') { + marker++; + size--; + break; + } + + std::string attr_name; + std::string attr_type; + std::vector<unsigned char> data; + size_t marker_size; + if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size, + marker, size)) { + std::stringstream ss; + ss << "Failed to parse attribute\n"; + tinyexr::SetErrorMessage(ss.str(), err); + return TINYEXR_ERROR_INVALID_DATA; + } + marker += marker_size; + size -= marker_size; + + if (attr_name.compare("compression") == 0) { + compression_type = data[0]; + if (compression_type > TINYEXR_COMPRESSIONTYPE_PIZ) { + std::stringstream ss; + ss << "Unsupported compression type : " << compression_type; + tinyexr::SetErrorMessage(ss.str(), err); + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; + } + + if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) { + num_scanline_blocks = 16; + } + + } else if (attr_name.compare("channels") == 0) { + // name: zero-terminated string, from 1 to 255 bytes long + // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2 + // pLinear: unsigned char, possible values are 0 and 1 + // reserved: three chars, should be zero + // xSampling: int + // ySampling: int + + if (!tinyexr::ReadChannelInfo(channels, data)) { + tinyexr::SetErrorMessage("Failed to parse channel info", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + num_channels = static_cast<int>(channels.size()); + + if (num_channels < 1) { + tinyexr::SetErrorMessage("Invalid channels format", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + } else if (attr_name.compare("dataWindow") == 0) { + memcpy(&dx, &data.at(0), sizeof(int)); + memcpy(&dy, &data.at(4), sizeof(int)); + memcpy(&dw, &data.at(8), sizeof(int)); + memcpy(&dh, &data.at(12), sizeof(int)); + tinyexr::swap4(&dx); + tinyexr::swap4(&dy); + tinyexr::swap4(&dw); + tinyexr::swap4(&dh); + + } else if (attr_name.compare("displayWindow") == 0) { + int x; + int y; + int w; + int h; + memcpy(&x, &data.at(0), sizeof(int)); + memcpy(&y, &data.at(4), sizeof(int)); + memcpy(&w, &data.at(8), sizeof(int)); + memcpy(&h, &data.at(12), sizeof(int)); + tinyexr::swap4(&x); + tinyexr::swap4(&y); + tinyexr::swap4(&w); + tinyexr::swap4(&h); + } + } + + TINYEXR_CHECK_AND_RETURN_C(dx >= 0, TINYEXR_ERROR_INVALID_DATA); + TINYEXR_CHECK_AND_RETURN_C(dy >= 0, TINYEXR_ERROR_INVALID_DATA); + TINYEXR_CHECK_AND_RETURN_C(dw >= 0, TINYEXR_ERROR_INVALID_DATA); + TINYEXR_CHECK_AND_RETURN_C(dh >= 0, TINYEXR_ERROR_INVALID_DATA); + TINYEXR_CHECK_AND_RETURN_C(num_channels >= 1, TINYEXR_ERROR_INVALID_DATA); + + int data_width = dw - dx + 1; + int data_height = dh - dy + 1; + + // Read offset tables. + int num_blocks = data_height / num_scanline_blocks; + if (num_blocks * num_scanline_blocks < data_height) { + num_blocks++; + } + + std::vector<tinyexr::tinyexr_int64> offsets(static_cast<size_t>(num_blocks)); + + for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) { + tinyexr::tinyexr_int64 offset; + memcpy(&offset, marker, sizeof(tinyexr::tinyexr_int64)); + tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offset)); + marker += sizeof(tinyexr::tinyexr_int64); // = 8 + offsets[y] = offset; + } + +#if TINYEXR_USE_PIZ + if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) || + (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) || + (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) || + (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) || + (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ)) { +#else + if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) || + (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) || + (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) || + (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) { +#endif + // OK + } else { + tinyexr::SetErrorMessage("Unsupported compression format", err); + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; + } + + deep_image->image = static_cast<float ***>( + malloc(sizeof(float **) * static_cast<size_t>(num_channels))); + for (int c = 0; c < num_channels; c++) { + deep_image->image[c] = static_cast<float **>( + malloc(sizeof(float *) * static_cast<size_t>(data_height))); + for (int y = 0; y < data_height; y++) { + } + } + + deep_image->offset_table = static_cast<int **>( + malloc(sizeof(int *) * static_cast<size_t>(data_height))); + for (int y = 0; y < data_height; y++) { + deep_image->offset_table[y] = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(data_width))); + } + + for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) { + const unsigned char *data_ptr = + reinterpret_cast<const unsigned char *>(head + offsets[y]); + + // int: y coordinate + // int64: packed size of pixel offset table + // int64: packed size of sample data + // int64: unpacked size of sample data + // compressed pixel offset table + // compressed sample data + int line_no; + tinyexr::tinyexr_int64 packedOffsetTableSize; + tinyexr::tinyexr_int64 packedSampleDataSize; + tinyexr::tinyexr_int64 unpackedSampleDataSize; + memcpy(&line_no, data_ptr, sizeof(int)); + memcpy(&packedOffsetTableSize, data_ptr + 4, + sizeof(tinyexr::tinyexr_int64)); + memcpy(&packedSampleDataSize, data_ptr + 12, + sizeof(tinyexr::tinyexr_int64)); + memcpy(&unpackedSampleDataSize, data_ptr + 20, + sizeof(tinyexr::tinyexr_int64)); + + tinyexr::swap4(&line_no); + tinyexr::swap8( + reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedOffsetTableSize)); + tinyexr::swap8( + reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedSampleDataSize)); + tinyexr::swap8( + reinterpret_cast<tinyexr::tinyexr_uint64 *>(&unpackedSampleDataSize)); + + std::vector<int> pixelOffsetTable(static_cast<size_t>(data_width)); + + // decode pixel offset table. + { + unsigned long dstLen = + static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int)); + if (!tinyexr::DecompressZip( + reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)), + &dstLen, data_ptr + 28, + static_cast<unsigned long>(packedOffsetTableSize))) { + return false; + } + + TINYEXR_CHECK_AND_RETURN_C(dstLen == pixelOffsetTable.size() * sizeof(int), TINYEXR_ERROR_INVALID_DATA); + for (size_t i = 0; i < static_cast<size_t>(data_width); i++) { + deep_image->offset_table[y][i] = pixelOffsetTable[i]; + } + } + + std::vector<unsigned char> sample_data( + static_cast<size_t>(unpackedSampleDataSize)); + + // decode sample data. + { + unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize); + if (dstLen) { + if (!tinyexr::DecompressZip( + reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen, + data_ptr + 28 + packedOffsetTableSize, + static_cast<unsigned long>(packedSampleDataSize))) { + return false; + } + TINYEXR_CHECK_AND_RETURN_C(dstLen == static_cast<unsigned long>(unpackedSampleDataSize), TINYEXR_ERROR_INVALID_DATA); + } + } + + // decode sample + int sampleSize = -1; + std::vector<int> channel_offset_list(static_cast<size_t>(num_channels)); + { + int channel_offset = 0; + for (size_t i = 0; i < static_cast<size_t>(num_channels); i++) { + channel_offset_list[i] = channel_offset; + if (channels[i].pixel_type == TINYEXR_PIXELTYPE_UINT) { // UINT + channel_offset += 4; + } else if (channels[i].pixel_type == TINYEXR_PIXELTYPE_HALF) { // half + channel_offset += 2; + } else if (channels[i].pixel_type == + TINYEXR_PIXELTYPE_FLOAT) { // float + channel_offset += 4; + } else { + tinyexr::SetErrorMessage("Invalid pixel_type in chnnels.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + sampleSize = channel_offset; + } + TINYEXR_CHECK_AND_RETURN_C(sampleSize >= 2, TINYEXR_ERROR_INVALID_DATA); + + TINYEXR_CHECK_AND_RETURN_C(static_cast<size_t>( + pixelOffsetTable[static_cast<size_t>(data_width - 1)] * + sampleSize) == sample_data.size(), TINYEXR_ERROR_INVALID_DATA); + int samples_per_line = static_cast<int>(sample_data.size()) / sampleSize; + + // + // Alloc memory + // + + // + // pixel data is stored as image[channels][pixel_samples] + // + { + tinyexr::tinyexr_uint64 data_offset = 0; + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { + deep_image->image[c][y] = static_cast<float *>( + malloc(sizeof(float) * static_cast<size_t>(samples_per_line))); + + if (channels[c].pixel_type == 0) { // UINT + for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) { + unsigned int ui; + unsigned int *src_ptr = reinterpret_cast<unsigned int *>( + &sample_data.at(size_t(data_offset) + x * sizeof(int))); + tinyexr::cpy4(&ui, src_ptr); + deep_image->image[c][y][x] = static_cast<float>(ui); // @fixme + } + data_offset += + sizeof(unsigned int) * static_cast<size_t>(samples_per_line); + } else if (channels[c].pixel_type == 1) { // half + for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) { + tinyexr::FP16 f16; + const unsigned short *src_ptr = reinterpret_cast<unsigned short *>( + &sample_data.at(size_t(data_offset) + x * sizeof(short))); + tinyexr::cpy2(&(f16.u), src_ptr); + tinyexr::FP32 f32 = half_to_float(f16); + deep_image->image[c][y][x] = f32.f; + } + data_offset += sizeof(short) * static_cast<size_t>(samples_per_line); + } else { // float + for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) { + float f; + const float *src_ptr = reinterpret_cast<float *>( + &sample_data.at(size_t(data_offset) + x * sizeof(float))); + tinyexr::cpy4(&f, src_ptr); + deep_image->image[c][y][x] = f; + } + data_offset += sizeof(float) * static_cast<size_t>(samples_per_line); + } + } + } + } // y + + deep_image->width = data_width; + deep_image->height = data_height; + + deep_image->channel_names = static_cast<const char **>( + malloc(sizeof(const char *) * static_cast<size_t>(num_channels))); + for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) { +#ifdef _WIN32 + deep_image->channel_names[c] = _strdup(channels[c].name.c_str()); +#else + deep_image->channel_names[c] = strdup(channels[c].name.c_str()); +#endif + } + deep_image->num_channels = num_channels; + + return TINYEXR_SUCCESS; +} + +void InitEXRImage(EXRImage *exr_image) { + if (exr_image == NULL) { + return; + } + + exr_image->width = 0; + exr_image->height = 0; + exr_image->num_channels = 0; + + exr_image->images = NULL; + exr_image->tiles = NULL; + exr_image->next_level = NULL; + exr_image->level_x = 0; + exr_image->level_y = 0; + + exr_image->num_tiles = 0; +} + +void FreeEXRErrorMessage(const char *msg) { + if (msg) { + free(reinterpret_cast<void *>(const_cast<char *>(msg))); + } + return; +} + +void InitEXRHeader(EXRHeader *exr_header) { + if (exr_header == NULL) { + return; + } + + memset(exr_header, 0, sizeof(EXRHeader)); +} + +int FreeEXRHeader(EXRHeader *exr_header) { + if (exr_header == NULL) { + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if (exr_header->channels) { + free(exr_header->channels); + } + + if (exr_header->pixel_types) { + free(exr_header->pixel_types); + } + + if (exr_header->requested_pixel_types) { + free(exr_header->requested_pixel_types); + } + + for (int i = 0; i < exr_header->num_custom_attributes; i++) { + if (exr_header->custom_attributes[i].value) { + free(exr_header->custom_attributes[i].value); + } + } + + if (exr_header->custom_attributes) { + free(exr_header->custom_attributes); + } + + EXRSetNameAttr(exr_header, NULL); + + return TINYEXR_SUCCESS; +} + +void EXRSetNameAttr(EXRHeader* exr_header, const char* name) { + if (exr_header == NULL) { + return; + } + memset(exr_header->name, 0, 256); + if (name != NULL) { + size_t len = std::min(strlen(name), size_t(255)); + if (len) { + memcpy(exr_header->name, name, len); + } + } +} + +int EXRNumLevels(const EXRImage* exr_image) { + if (exr_image == NULL) return 0; + if(exr_image->images) return 1; // scanlines + int levels = 1; + const EXRImage* level_image = exr_image; + while((level_image = level_image->next_level)) ++levels; + return levels; +} + +int FreeEXRImage(EXRImage *exr_image) { + if (exr_image == NULL) { + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if (exr_image->next_level) { + FreeEXRImage(exr_image->next_level); + delete exr_image->next_level; + } + + for (int i = 0; i < exr_image->num_channels; i++) { + if (exr_image->images && exr_image->images[i]) { + free(exr_image->images[i]); + } + } + + if (exr_image->images) { + free(exr_image->images); + } + + if (exr_image->tiles) { + for (int tid = 0; tid < exr_image->num_tiles; tid++) { + for (int i = 0; i < exr_image->num_channels; i++) { + if (exr_image->tiles[tid].images && exr_image->tiles[tid].images[i]) { + free(exr_image->tiles[tid].images[i]); + } + } + if (exr_image->tiles[tid].images) { + free(exr_image->tiles[tid].images); + } + } + free(exr_image->tiles); + } + + return TINYEXR_SUCCESS; +} + +int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, + const char *filename, const char **err) { + if (exr_header == NULL || exr_version == NULL || filename == NULL) { + tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile", + err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + MemoryMappedFile file(filename); + if (!file.valid()) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } + + return ParseEXRHeaderFromMemory(exr_header, exr_version, file.data, file.size, + err); +} + +int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers, + int *num_headers, + const EXRVersion *exr_version, + const unsigned char *memory, size_t size, + const char **err) { + if (memory == NULL || exr_headers == NULL || num_headers == NULL || + exr_version == NULL) { + // Invalid argument + tinyexr::SetErrorMessage( + "Invalid argument for ParseEXRMultipartHeaderFromMemory", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if (size < tinyexr::kEXRVersionSize) { + tinyexr::SetErrorMessage("Data size too short", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + const unsigned char *marker = memory + tinyexr::kEXRVersionSize; + size_t marker_size = size - tinyexr::kEXRVersionSize; + + std::vector<tinyexr::HeaderInfo> infos; + + for (;;) { + tinyexr::HeaderInfo info; + info.clear(); + + std::string err_str; + bool empty_header = false; + int ret = ParseEXRHeader(&info, &empty_header, exr_version, &err_str, + marker, marker_size); + + if (ret != TINYEXR_SUCCESS) { + + // Free malloc-allocated memory here. + for (size_t i = 0; i < info.attributes.size(); i++) { + if (info.attributes[i].value) { + free(info.attributes[i].value); + } + } + + tinyexr::SetErrorMessage(err_str, err); + return ret; + } + + if (empty_header) { + marker += 1; // skip '\0' + break; + } + + // `chunkCount` must exist in the header. + if (info.chunk_count == 0) { + + // Free malloc-allocated memory here. + for (size_t i = 0; i < info.attributes.size(); i++) { + if (info.attributes[i].value) { + free(info.attributes[i].value); + } + } + + tinyexr::SetErrorMessage( + "`chunkCount' attribute is not found in the header.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + + infos.push_back(info); + + // move to next header. + marker += info.header_len; + size -= info.header_len; + } + + // allocate memory for EXRHeader and create array of EXRHeader pointers. + (*exr_headers) = + static_cast<EXRHeader **>(malloc(sizeof(EXRHeader *) * infos.size())); + + + int retcode = TINYEXR_SUCCESS; + + for (size_t i = 0; i < infos.size(); i++) { + EXRHeader *exr_header = static_cast<EXRHeader *>(malloc(sizeof(EXRHeader))); + memset(exr_header, 0, sizeof(EXRHeader)); + + std::string warn; + std::string _err; + if (!ConvertHeader(exr_header, infos[i], &warn, &_err)) { + + // Free malloc-allocated memory here. + for (size_t k = 0; k < infos[i].attributes.size(); i++) { + if (infos[i].attributes[k].value) { + free(infos[i].attributes[k].value); + } + } + + if (!_err.empty()) { + tinyexr::SetErrorMessage( + _err, err); + } + // continue to converting headers + retcode = TINYEXR_ERROR_INVALID_HEADER; + } + + exr_header->multipart = exr_version->multipart ? 1 : 0; + + (*exr_headers)[i] = exr_header; + } + + (*num_headers) = static_cast<int>(infos.size()); + + return retcode; +} + +int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers, + const EXRVersion *exr_version, + const char *filename, const char **err) { + if (exr_headers == NULL || num_headers == NULL || exr_version == NULL || + filename == NULL) { + tinyexr::SetErrorMessage( + "Invalid argument for ParseEXRMultipartHeaderFromFile()", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + MemoryMappedFile file(filename); + if (!file.valid()) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } + + return ParseEXRMultipartHeaderFromMemory( + exr_headers, num_headers, exr_version, file.data, file.size, err); +} + +int ParseEXRVersionFromMemory(EXRVersion *version, const unsigned char *memory, + size_t size) { + if (version == NULL || memory == NULL) { + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + if (size < tinyexr::kEXRVersionSize) { + return TINYEXR_ERROR_INVALID_DATA; + } + + const unsigned char *marker = memory; + + // Header check. + { + const char header[] = {0x76, 0x2f, 0x31, 0x01}; + + if (memcmp(marker, header, 4) != 0) { + return TINYEXR_ERROR_INVALID_MAGIC_NUMBER; + } + marker += 4; + } + + version->tiled = false; + version->long_name = false; + version->non_image = false; + version->multipart = false; + + // Parse version header. + { + // must be 2 + if (marker[0] != 2) { + return TINYEXR_ERROR_INVALID_EXR_VERSION; + } + + if (version == NULL) { + return TINYEXR_SUCCESS; // May OK + } + + version->version = 2; + + if (marker[1] & 0x2) { // 9th bit + version->tiled = true; + } + if (marker[1] & 0x4) { // 10th bit + version->long_name = true; + } + if (marker[1] & 0x8) { // 11th bit + version->non_image = true; // (deep image) + } + if (marker[1] & 0x10) { // 12th bit + version->multipart = true; + } + } + + return TINYEXR_SUCCESS; +} + +int ParseEXRVersionFromFile(EXRVersion *version, const char *filename) { + if (filename == NULL) { + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + FILE *fp = NULL; +#ifdef _WIN32 +#if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) // MSVC, MinGW GCC, or Clang. + errno_t err = _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (err != 0) { + // TODO(syoyo): return wfopen_s erro code + return TINYEXR_ERROR_CANT_OPEN_FILE; + } +#else + // Unknown compiler or MinGW without MINGW_HAS_SECURE_API. + fp = fopen(filename, "rb"); +#endif +#else + fp = fopen(filename, "rb"); +#endif + if (!fp) { + return TINYEXR_ERROR_CANT_OPEN_FILE; + } + + // Try to read kEXRVersionSize bytes; if the file is shorter than + // kEXRVersionSize, this will produce an error. This avoids a call to + // fseek(fp, 0, SEEK_END), which is not required to be supported by C + // implementations. + unsigned char buf[tinyexr::kEXRVersionSize]; + size_t ret = fread(&buf[0], 1, tinyexr::kEXRVersionSize, fp); + fclose(fp); + + if (ret != tinyexr::kEXRVersionSize) { + return TINYEXR_ERROR_INVALID_FILE; + } + + return ParseEXRVersionFromMemory(version, buf, tinyexr::kEXRVersionSize); +} + +int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, + const EXRHeader **exr_headers, + unsigned int num_parts, + const unsigned char *memory, + const size_t size, const char **err) { + if (exr_images == NULL || exr_headers == NULL || num_parts == 0 || + memory == NULL || (size <= tinyexr::kEXRVersionSize)) { + tinyexr::SetErrorMessage( + "Invalid argument for LoadEXRMultipartImageFromMemory()", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + // compute total header size. + size_t total_header_size = 0; + for (unsigned int i = 0; i < num_parts; i++) { + if (exr_headers[i]->header_len == 0) { + tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + total_header_size += exr_headers[i]->header_len; + } + + const char *marker = reinterpret_cast<const char *>( + memory + total_header_size + 4 + + 4); // +8 for magic number and version header. + + marker += 1; // Skip empty header. + + // NOTE 1: + // In multipart image, There is 'part number' before chunk data. + // 4 byte : part number + // 4+ : chunk + // + // NOTE 2: + // EXR spec says 'part number' is 'unsigned long' but actually this is + // 'unsigned int(4 bytes)' in OpenEXR implementation... + // http://www.openexr.com/openexrfilelayout.pdf + + // Load chunk offset table. + std::vector<tinyexr::OffsetData> chunk_offset_table_list; + chunk_offset_table_list.reserve(num_parts); + for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) { + chunk_offset_table_list.resize(chunk_offset_table_list.size() + 1); + tinyexr::OffsetData& offset_data = chunk_offset_table_list.back(); + if (!exr_headers[i]->tiled || exr_headers[i]->tile_level_mode == TINYEXR_TILE_ONE_LEVEL) { + tinyexr::InitSingleResolutionOffsets(offset_data, size_t(exr_headers[i]->chunk_count)); + std::vector<tinyexr::tinyexr_uint64>& offset_table = offset_data.offsets[0][0]; + + for (size_t c = 0; c < offset_table.size(); c++) { + tinyexr::tinyexr_uint64 offset; + memcpy(&offset, marker, 8); + tinyexr::swap8(&offset); + + if (offset >= size) { + tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.", + err); + return TINYEXR_ERROR_INVALID_DATA; + } + + offset_table[c] = offset + 4; // +4 to skip 'part number' + marker += 8; + } + } else { + { + std::vector<int> num_x_tiles, num_y_tiles; + if (!tinyexr::PrecalculateTileInfo(num_x_tiles, num_y_tiles, exr_headers[i])) { + tinyexr::SetErrorMessage("Invalid tile info.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + int num_blocks = InitTileOffsets(offset_data, exr_headers[i], num_x_tiles, num_y_tiles); + if (num_blocks != exr_headers[i]->chunk_count) { + tinyexr::SetErrorMessage("Invalid offset table size.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) { + for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) { + for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) { + tinyexr::tinyexr_uint64 offset; + memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64)); + tinyexr::swap8(&offset); + if (offset >= size) { + tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.", + err); + return TINYEXR_ERROR_INVALID_DATA; + } + offset_data.offsets[l][dy][dx] = offset + 4; // +4 to skip 'part number' + marker += sizeof(tinyexr::tinyexr_uint64); // = 8 + } + } + } + } + } + + // Decode image. + for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) { + tinyexr::OffsetData &offset_data = chunk_offset_table_list[i]; + + // First check 'part number' is identical to 'i' + for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) + for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) + for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) { + + const unsigned char *part_number_addr = + memory + offset_data.offsets[l][dy][dx] - 4; // -4 to move to 'part number' field. + unsigned int part_no; + memcpy(&part_no, part_number_addr, sizeof(unsigned int)); // 4 + tinyexr::swap4(&part_no); + + if (part_no != i) { + tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.", + err); + return TINYEXR_ERROR_INVALID_DATA; + } + } + + std::string e; + int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_data, + memory, size, &e); + if (ret != TINYEXR_SUCCESS) { + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } + return ret; + } + } + + return TINYEXR_SUCCESS; +} + +int LoadEXRMultipartImageFromFile(EXRImage *exr_images, + const EXRHeader **exr_headers, + unsigned int num_parts, const char *filename, + const char **err) { + if (exr_images == NULL || exr_headers == NULL || num_parts == 0) { + tinyexr::SetErrorMessage( + "Invalid argument for LoadEXRMultipartImageFromFile", err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + MemoryMappedFile file(filename); + if (!file.valid()) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } + + return LoadEXRMultipartImageFromMemory(exr_images, exr_headers, num_parts, + file.data, file.size, err); +} + +int SaveEXRToMemory(const float *data, int width, int height, int components, + const int save_as_fp16, const unsigned char **outbuf, const char **err) { + + if ((components == 1) || components == 3 || components == 4) { + // OK + } else { + std::stringstream ss; + ss << "Unsupported component value : " << components << std::endl; + + tinyexr::SetErrorMessage(ss.str(), err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + EXRHeader header; + InitEXRHeader(&header); + + if ((width < 16) && (height < 16)) { + // No compression for small image. + header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE; + } else { + header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP; + } + + EXRImage image; + InitEXRImage(&image); + + image.num_channels = components; + + std::vector<float> images[4]; + + if (components == 1) { + images[0].resize(static_cast<size_t>(width * height)); + memcpy(images[0].data(), data, sizeof(float) * size_t(width * height)); + } else { + images[0].resize(static_cast<size_t>(width * height)); + images[1].resize(static_cast<size_t>(width * height)); + images[2].resize(static_cast<size_t>(width * height)); + images[3].resize(static_cast<size_t>(width * height)); + + // Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers + for (size_t i = 0; i < static_cast<size_t>(width * height); i++) { + images[0][i] = data[static_cast<size_t>(components) * i + 0]; + images[1][i] = data[static_cast<size_t>(components) * i + 1]; + images[2][i] = data[static_cast<size_t>(components) * i + 2]; + if (components == 4) { + images[3][i] = data[static_cast<size_t>(components) * i + 3]; + } + } + } + + float *image_ptr[4] = {0, 0, 0, 0}; + if (components == 4) { + image_ptr[0] = &(images[3].at(0)); // A + image_ptr[1] = &(images[2].at(0)); // B + image_ptr[2] = &(images[1].at(0)); // G + image_ptr[3] = &(images[0].at(0)); // R + } else if (components == 3) { + image_ptr[0] = &(images[2].at(0)); // B + image_ptr[1] = &(images[1].at(0)); // G + image_ptr[2] = &(images[0].at(0)); // R + } else if (components == 1) { + image_ptr[0] = &(images[0].at(0)); // A + } + + image.images = reinterpret_cast<unsigned char **>(image_ptr); + image.width = width; + image.height = height; + + header.num_channels = components; + header.channels = static_cast<EXRChannelInfo *>(malloc( + sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels))); + // Must be (A)BGR order, since most of EXR viewers expect this channel order. + if (components == 4) { +#ifdef _MSC_VER + strncpy_s(header.channels[0].name, "A", 255); + strncpy_s(header.channels[1].name, "B", 255); + strncpy_s(header.channels[2].name, "G", 255); + strncpy_s(header.channels[3].name, "R", 255); +#else + strncpy(header.channels[0].name, "A", 255); + strncpy(header.channels[1].name, "B", 255); + strncpy(header.channels[2].name, "G", 255); + strncpy(header.channels[3].name, "R", 255); +#endif + header.channels[0].name[strlen("A")] = '\0'; + header.channels[1].name[strlen("B")] = '\0'; + header.channels[2].name[strlen("G")] = '\0'; + header.channels[3].name[strlen("R")] = '\0'; + } else if (components == 3) { +#ifdef _MSC_VER + strncpy_s(header.channels[0].name, "B", 255); + strncpy_s(header.channels[1].name, "G", 255); + strncpy_s(header.channels[2].name, "R", 255); +#else + strncpy(header.channels[0].name, "B", 255); + strncpy(header.channels[1].name, "G", 255); + strncpy(header.channels[2].name, "R", 255); +#endif + header.channels[0].name[strlen("B")] = '\0'; + header.channels[1].name[strlen("G")] = '\0'; + header.channels[2].name[strlen("R")] = '\0'; + } else { +#ifdef _MSC_VER + strncpy_s(header.channels[0].name, "A", 255); +#else + strncpy(header.channels[0].name, "A", 255); +#endif + header.channels[0].name[strlen("A")] = '\0'; + } + + header.pixel_types = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(header.num_channels))); + header.requested_pixel_types = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(header.num_channels))); + for (int i = 0; i < header.num_channels; i++) { + header.pixel_types[i] = + TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image + + if (save_as_fp16 > 0) { + header.requested_pixel_types[i] = + TINYEXR_PIXELTYPE_HALF; // save with half(fp16) pixel format + } else { + header.requested_pixel_types[i] = + TINYEXR_PIXELTYPE_FLOAT; // save with float(fp32) pixel format(i.e. + // no precision reduction) + } + } + + + unsigned char *mem_buf; + size_t mem_size = SaveEXRImageToMemory(&image, &header, &mem_buf, err); + + if (mem_size == 0) { + return TINYEXR_ERROR_SERIALIZATION_FAILED; + } + + free(header.channels); + free(header.pixel_types); + free(header.requested_pixel_types); + + if (mem_size > size_t(std::numeric_limits<int>::max())) { + free(mem_buf); + return TINYEXR_ERROR_DATA_TOO_LARGE; + } + + (*outbuf) = mem_buf; + + return int(mem_size); +} + +int SaveEXR(const float *data, int width, int height, int components, + const int save_as_fp16, const char *outfilename, const char **err) { + if ((components == 1) || components == 3 || components == 4) { + // OK + } else { + std::stringstream ss; + ss << "Unsupported component value : " << components << std::endl; + + tinyexr::SetErrorMessage(ss.str(), err); + return TINYEXR_ERROR_INVALID_ARGUMENT; + } + + EXRHeader header; + InitEXRHeader(&header); + + if ((width < 16) && (height < 16)) { + // No compression for small image. + header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE; + } else { + header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP; + } + + EXRImage image; + InitEXRImage(&image); + + image.num_channels = components; + + std::vector<float> images[4]; + const size_t pixel_count = + static_cast<size_t>(width) * static_cast<size_t>(height); + + if (components == 1) { + images[0].resize(pixel_count); + memcpy(images[0].data(), data, sizeof(float) * pixel_count); + } else { + images[0].resize(pixel_count); + images[1].resize(pixel_count); + images[2].resize(pixel_count); + images[3].resize(pixel_count); + + // Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers + for (size_t i = 0; i < pixel_count; i++) { + images[0][i] = data[static_cast<size_t>(components) * i + 0]; + images[1][i] = data[static_cast<size_t>(components) * i + 1]; + images[2][i] = data[static_cast<size_t>(components) * i + 2]; + if (components == 4) { + images[3][i] = data[static_cast<size_t>(components) * i + 3]; + } + } + } + + float *image_ptr[4] = {0, 0, 0, 0}; + if (components == 4) { + image_ptr[0] = &(images[3].at(0)); // A + image_ptr[1] = &(images[2].at(0)); // B + image_ptr[2] = &(images[1].at(0)); // G + image_ptr[3] = &(images[0].at(0)); // R + } else if (components == 3) { + image_ptr[0] = &(images[2].at(0)); // B + image_ptr[1] = &(images[1].at(0)); // G + image_ptr[2] = &(images[0].at(0)); // R + } else if (components == 1) { + image_ptr[0] = &(images[0].at(0)); // A + } + + image.images = reinterpret_cast<unsigned char **>(image_ptr); + image.width = width; + image.height = height; + + header.num_channels = components; + header.channels = static_cast<EXRChannelInfo *>(malloc( + sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels))); + // Must be (A)BGR order, since most of EXR viewers expect this channel order. + if (components == 4) { +#ifdef _MSC_VER + strncpy_s(header.channels[0].name, "A", 255); + strncpy_s(header.channels[1].name, "B", 255); + strncpy_s(header.channels[2].name, "G", 255); + strncpy_s(header.channels[3].name, "R", 255); +#else + strncpy(header.channels[0].name, "A", 255); + strncpy(header.channels[1].name, "B", 255); + strncpy(header.channels[2].name, "G", 255); + strncpy(header.channels[3].name, "R", 255); +#endif + header.channels[0].name[strlen("A")] = '\0'; + header.channels[1].name[strlen("B")] = '\0'; + header.channels[2].name[strlen("G")] = '\0'; + header.channels[3].name[strlen("R")] = '\0'; + } else if (components == 3) { +#ifdef _MSC_VER + strncpy_s(header.channels[0].name, "B", 255); + strncpy_s(header.channels[1].name, "G", 255); + strncpy_s(header.channels[2].name, "R", 255); +#else + strncpy(header.channels[0].name, "B", 255); + strncpy(header.channels[1].name, "G", 255); + strncpy(header.channels[2].name, "R", 255); +#endif + header.channels[0].name[strlen("B")] = '\0'; + header.channels[1].name[strlen("G")] = '\0'; + header.channels[2].name[strlen("R")] = '\0'; + } else { +#ifdef _MSC_VER + strncpy_s(header.channels[0].name, "A", 255); +#else + strncpy(header.channels[0].name, "A", 255); +#endif + header.channels[0].name[strlen("A")] = '\0'; + } + + header.pixel_types = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(header.num_channels))); + header.requested_pixel_types = static_cast<int *>( + malloc(sizeof(int) * static_cast<size_t>(header.num_channels))); + for (int i = 0; i < header.num_channels; i++) { + header.pixel_types[i] = + TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image + + if (save_as_fp16 > 0) { + header.requested_pixel_types[i] = + TINYEXR_PIXELTYPE_HALF; // save with half(fp16) pixel format + } else { + header.requested_pixel_types[i] = + TINYEXR_PIXELTYPE_FLOAT; // save with float(fp32) pixel format(i.e. + // no precision reduction) + } + } + + int ret = SaveEXRImageToFile(&image, &header, outfilename, err); + if (ret != TINYEXR_SUCCESS) { + return ret; + } + + free(header.channels); + free(header.pixel_types); + free(header.requested_pixel_types); + + return ret; +} + +#ifdef __clang__ +// zero-as-null-pointer-constant +#pragma clang diagnostic pop +#endif + +#endif // TINYEXR_IMPLEMENTATION_DEFINED +#endif // TINYEXR_IMPLEMENTATION diff --git a/external/tiny_exr/tinyexr_impl.cpp b/external/tiny_exr/tinyexr_impl.cpp new file mode 100644 index 00000000..55351e80 --- /dev/null +++ b/external/tiny_exr/tinyexr_impl.cpp @@ -0,0 +1,9 @@ +// Copyright 2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +// Use stb_image zlib implementation: +#define TINYEXR_USE_MINIZ 0 +#define TINYEXR_USE_STB_ZLIB 1 +#define TINYEXR_USE_THREAD 1 +#define TINYEXR_IMPLEMENTATION +#include "tinyexr.h" diff --git a/gitlab/build.sh b/gitlab/build.sh index 574c7e2e..e6b2e672 100755 --- a/gitlab/build.sh +++ b/gitlab/build.sh @@ -23,6 +23,7 @@ then -D ENABLE_OPENIMAGEIO=OFF \ -D ENABLE_OPENVDB=OFF \ -D ENABLE_EXR=OFF \ + -D OSPRAY_TAG=".sycl" \ -D OSPSTUDIO_SIGN_FILE=$SIGN_FILE_LINUX \ .. cmake --build . --parallel $THREADS --config Release diff --git a/gitlab/image-comparison.py b/gitlab/image-comparison.py index 9e8d36cb..911999df 100644 --- a/gitlab/image-comparison.py +++ b/gitlab/image-comparison.py @@ -23,15 +23,17 @@ def evaluate_metrics(reference, candidate): # ssim provides high scores one of the images is blured or the color space is shifted # further reading: # https://en.wikipedia.org/wiki/Structural_similarity - # "ssim": skimage.metrics.structural_similarity(reference, candidate, multichannel=True), + # "ssim": skimage.metrics.structural_similarity(reference, candidate, channel_axis=-1), # Mean Squared Error (MSE) is one of the most commonly used image quality measures, but receives strong criticism as # it doesn't reflect the way the human visual systems perceive images very well. An image pair with # high MSE might still look very similar to a human. - "mse": skimage.metrics.mean_squared_error(reference, candidate), + # "mse": skimage.metrics.mean_squared_error(reference, candidate), + # Peak Signal to Noise Ratio (PSNR) is based on MSE and brought to a logarithmic scale in the decibel unit - #"psnr": skimage.metrics.peak_signal_noise_ratio(reference, candidate), + # "psnr": skimage.metrics.peak_signal_noise_ratio(reference, candidate), + # Normalized Root MSE (NRMSE) # "nrmse": skimage.metrics.normalized_root_mse(reference, candidate), @@ -45,7 +47,7 @@ def evaluate_metrics(reference, candidate): # "vif": vifp(reference, candidate), # Universal Quality Index (UQI) - # "uqi": uqi(reference, candidate), + "uqi": uqi(reference, candidate), } def evaluate_passed(metrics, threshold): @@ -59,7 +61,8 @@ def evaluate_passed(metrics, threshold): # PSNR for image compression in 8bit is typically in the range [30, 50] # "psnr": metrics["psnr"] > 20.0, # MSE - "mse": metrics["mse"] > threshold + #"mse": metrics["mse"] > threshold + "uqi": metrics["uqi"] > threshold } def print_report(metrics_report): @@ -110,10 +113,10 @@ def normalize_images(reference, candidate): return reference, candidate if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Compare two images with MSE.') + parser = argparse.ArgumentParser(description='Compare two images with UQI.') parser.add_argument("--reference", "-g", help="Gold image for comparison", default="") parser.add_argument("--candidate", "-c", help="Image to be compared", default="") - parser.add_argument("--mse", "-m", help="Use mse to measure difference.") + parser.add_argument("--uqi", "-q", help="Use uqi to measure difference.") args = parser.parse_args() reference_path = Path(args.reference) @@ -126,12 +129,13 @@ def normalize_images(reference, candidate): reference_image, candidate_image = normalize_images(reference_image, candidate_image) # Compute metrics and compare images - results = evaluate(reference_image, candidate_image, float(args.mse)) - if float(results["metrics"]["mse"]) > float(args.mse): - print("Failure: MSE " + str(results["metrics"]["mse"]) + " is greater than the threshold " + args.mse) + results = evaluate(reference_image, candidate_image, float(args.uqi)) + print_report(results) + if not results["passed"]["uqi"]: + print("Failure: UQI " + str(results["metrics"]["uqi"]) + " is lower than the threshold " + args.uqi) sys.exit(-1) else: - print("Success: MSE " + str(results["metrics"]["mse"]) + " is less than the threshold " + args.mse) + print("Success: UQI " + str(results["metrics"]["uqi"]) + " is greater than the threshold " + args.uqi) sys.exit(0) # CLI output diff --git a/gitlab/ospray_studio.entitlements b/gitlab/ospray_studio.entitlements index 8cc185af..3134665f 100644 --- a/gitlab/ospray_studio.entitlements +++ b/gitlab/ospray_studio.entitlements @@ -2,7 +2,7 @@ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> - <key>com.apple.security.cs.disable-library-validation</key> - <true/> + <key>com.apple.security.cs.disable-library-validation</key><true/> + <key>com.apple.security.cs.allow-jit</key><true/> </dict> </plist> diff --git a/gitlab/run-dev-img-cmp.sh b/gitlab/run-dev-img-cmp.sh index 45fa4d6b..de1e1af9 100755 --- a/gitlab/run-dev-img-cmp.sh +++ b/gitlab/run-dev-img-cmp.sh @@ -19,7 +19,7 @@ model_dirs=(bunny hairball Peonies sponza) models=(bunny hairball Peonies sponza) cam_cnt=(2 1 1 1) -mse=(0.000001 0.000001 0.1 0.000001) +uqi=(0.999 0.999 0.999 0.999) results="model-results" mkdir -p ${results} @@ -42,7 +42,8 @@ for i in "${!models[@]}";do for ((j=0; j<${cam_cnt[i]}; j++)); do mv ${results}/c-${models[i]}.0000$j.png ${results}/c-${models[i]}.----$j.png - python3 $SCRIPT_DIR/image-comparison.py --reference $CACHE_DIR/datasets/${models[i]}/${models[i]}_$j\_gold.png --candidate ${results}/c-${models[i]}.----$j.png --mse ${mse[i]} + md5sum $CACHE_DIR/datasets/${models[i]}/${models[i]}_$j\_gold.png + python3 $SCRIPT_DIR/image-comparison.py --reference $CACHE_DIR/datasets/${models[i]}/${models[i]}_$j\_gold.png --candidate ${results}/c-${models[i]}.----$j.png --uqi ${uqi[i]} done -done \ No newline at end of file +done diff --git a/gitlab/run.sh b/gitlab/run.sh index 4ff1de46..f2a2b39a 100755 --- a/gitlab/run.sh +++ b/gitlab/run.sh @@ -6,7 +6,7 @@ set -e export DISPLAY=:1 export USER=root -mkdir -p $HOME/.vnc; echo testtest | vncpasswd -f > $HOME/.vnc/passwd; chmod 0600 $HOME/.vnc/passwd; touch $HOME/.vnc/xstartup; chmod +x $HOME/.vnc/xstartup +mkdir -p $HOME/.vnc; echo testtest | vncpasswd -f > $HOME/.vnc/passwd; chmod 0600 $HOME/.vnc/passwd; echo "sleep 2m" > $HOME/.vnc/xstartup; chmod +x $HOME/.vnc/xstartup vncserver $DISPLAY -geometry 1920x1080 #glxinfo # informational only @@ -17,7 +17,7 @@ export LD_LIBRARY_PATH cd ./build set +e -timeout --preserve-status 10s ospStudio +timeout --preserve-status 10s ospStudio $@ exitCode=$? echo "timeout originally returned: ${exitCode:?}" diff --git a/pysg/ospStudio.py b/pysg/ospStudio.py index c5e9ed25..82d24071 100644 --- a/pysg/ospStudio.py +++ b/pysg/ospStudio.py @@ -15,6 +15,16 @@ frame = sg.Frame() frame.createChild("windowSize", "vec2i", Any(window_size)) + +frame.createChildAs("renderer", "renderer_scivis") +#frame.createChildAs("renderer", "renderer_pathtracer") + +# Ensure framebuffer is float format and enable the denoiser +frame.child("framebuffer").child("floatFormat").setValue(True, True) +frame.denoiseFB = True +# Denoiser only enabled on pathtracer, by default. Set False to enable on another renderer +frame.denoiseOnlyPathTracer = False + world = frame.child("world") lightsMan = frame.child("lights") @@ -22,7 +32,7 @@ if len(files) > 0: for file in files: - importer = sg.getImporter(world, FileName(file)) + importer = sg.getImporter(world, FileName(file), True) importer.setLightsManager(lightsMan) importer.setMaterialRegistry(baseMaterialRegistry) importer.importScene() @@ -35,6 +45,8 @@ cam.createChild("aspect", "float", aspect) sg.updateCamera(cam, arcballCamera) +# Commit frame +frame.commit() frame.startNewFrame() frame.waitOnFrame() frame.saveFrame("studio_import.png", 0) diff --git a/pysg/pysg.cpp b/pysg/pysg.cpp index 958c2128..d1581aa7 100644 --- a/pysg/pysg.cpp +++ b/pysg/pysg.cpp @@ -42,8 +42,14 @@ static std::vector<std::string> init(const std::vector<std::string> &args) if (initError != OSP_NO_ERROR) { delete[] argv; std::cerr << "OSPRay not initialized correctly!" << std::endl; + return {}; } + // Check for module denoiser support after iniaitlizing OSPRay + bool denoiser = ospLoadModule("denoiser") == OSP_NO_ERROR; + std::cerr << "OpenImageDenoise is " << (denoiser ? "" : "not ") << "available" + << std::endl; + std::vector<std::string> newargs; if (argc > 1) @@ -282,6 +288,7 @@ PYBIND11_MODULE(pysg, sg) // MPI //////////////////////////////////////////// sg.def("assignMPI", &assignMPI); + sg.def("mpiBarrier", &sgMpiBarrier); // Importer functions //////////////////////////////////////////////////// sg.def("getImporter", &getImporter); @@ -368,6 +375,7 @@ PYBIND11_MODULE(pysg, sg) .def("bounds", &Node::bounds) .def( "setValue", static_cast<void (Node::*)(float, bool)>(&Node::setValue)) + .def("setValue", static_cast<void (Node::*)(bool, bool)>(&Node::setValue)) .def("setValue", static_cast<void (Node::*)(int, bool)>(&Node::setValue)) .def("setValue", static_cast<void (Node::*)(long, bool)>(&Node::setValue)) .def( @@ -469,9 +477,11 @@ PYBIND11_MODULE(pysg, sg) .def("saveFrame", &Frame::saveFrame) .def("waitOnFrame", &Frame::waitOnFrame) .def("startNewFrame", &Frame::startNewFrame) + .def("frameDuration", &Frame::frameDuration) .def_readwrite("immediatelyWait", &Frame::immediatelyWait) .def_readwrite("toneMapFB", &Frame::toneMapFB) - .def_readwrite("denoiseFB", &Frame::denoiseFB); + .def_readwrite("denoiseFB", &Frame::denoiseFB) + .def_readwrite("denoiseOnlyPathTracer", &Frame::denoiseOnlyPathTracer); py::class_<Renderer, OSPNode<ospray::cpp::Renderer, NodeType::RENDERER>, diff --git a/pysg/tutorial/studiobench1.py b/pysg/tutorial/studiobench1.py index ab644742..5309bd2c 100644 --- a/pysg/tutorial/studiobench1.py +++ b/pysg/tutorial/studiobench1.py @@ -13,7 +13,7 @@ args = sg.init(sys.argv) -sg.loadPlugin("vtk") +#sg.loadPlugin("vtk") #optional command line arguments scalarRange = None @@ -22,7 +22,7 @@ W = 1024 H = 768 numFrames = 100 - + for idx in range(0, len(args)): a = args[idx] if a == "-range": @@ -53,23 +53,31 @@ extps = volumename.rfind(".") filetype = volumename[extps:] volumename = volumename[0:extps] - + window_size = vec2i(W, H) aspect = Any(float(W) / H) - + frame = sg.Frame() frame.immediatelyWait = True frame.createChild("windowSize", "vec2i", Any(window_size)) - + renderer = sg.Renderer("scivis") -frame.createChildAs("renderer", "renderer_scivis") - +#frame.createChildAs("renderer", "renderer_scivis") +frame.createChildAs("renderer", "renderer_pathtracer") + +# Ensure framebuffer is float format and enable the denoiser +frame.child("framebuffer").child("floatFormat").setValue(True, True) +frame.denoiseFB = True +# Denoiser only enabled on pathtracer, by default. Set False to enable on another renderer +frame.denoiseOnlyPathTracer = False + + world = frame.child("world") - + lightsMan = frame.child("lights") baseMaterialRegistry = frame.child("baseMaterialRegistry") - -importer = sg.getImporter(world, FileName(filename)) + +importer = sg.getImporter(world, FileName(filename), True) importer.setLightsManager(lightsMan) importer.setMaterialRegistry(baseMaterialRegistry) importer.importScene() @@ -94,15 +102,14 @@ world.render() bounds = world.bounds() - + arcballCamera = ArcballCamera(bounds, window_size) cam = frame.child("camera") cam.createChild("aspect", "float", aspect) sg.updateCamera(cam, arcballCamera) - -# First frame will be "navigation" resolution. -# Render again for full sized frame. -frame.startNewFrame() + +# Commit frame +frame.commit() frame.startNewFrame() frame.waitOnFrame() frame.saveFrame("benchmark_initial.png", 0) @@ -115,8 +122,6 @@ sg.updateCamera(cam, arcballCamera) frame.startNewFrame() frame.waitOnFrame() - frame.startNewFrame() - frame.waitOnFrame() te = time.time()-ts elapsed = elapsed+te if te < min: diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..de2d18cd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +mpi4py==3.1.5 +numpy==1.26.1 diff --git a/resources/ospray_studio.rc b/resources/ospray_studio.rc index 811d0d59..0008daf2 100644 --- a/resources/ospray_studio.rc +++ b/resources/ospray_studio.rc @@ -24,7 +24,7 @@ BEGIN VALUE "FileDescription", "OSPRay Studio" VALUE "FileVersion", OSPRAY_STUDIO_VERSION VALUE "ProductVersion", OSPRAY_STUDIO_VERSION - VALUE "LegalCopyright", "© 2019-2021 Intel Corporation" + VALUE "LegalCopyright", "© 2019 Intel Corporation" VALUE "InternalName", "OSPRay Studio" VALUE "ProductName", "Intel® OSPRay Studio" END diff --git a/sg/CMakeLists.txt b/sg/CMakeLists.txt index 3177ed72..76b377ce 100644 --- a/sg/CMakeLists.txt +++ b/sg/CMakeLists.txt @@ -14,7 +14,7 @@ option(ENABLE_OPENIMAGEIO "Enable OpenImageIO support" OFF) if(ENABLE_OPENIMAGEIO) include(oiio) else() - message(STATUS "Building without OpenImageIO support. Using stb_image instead.") + message(STATUS "Building without OpenImageIO support.") endif() ## OpenVDB support ## @@ -174,6 +174,8 @@ PUBLIC json PRIVATE stb_image + tiny_exr + tiny_dng tiny_obj_loader tiny_gltf ) diff --git a/sg/Frame.cpp b/sg/Frame.cpp index fe22d6bb..65358d30 100644 --- a/sg/Frame.cpp +++ b/sg/Frame.cpp @@ -90,6 +90,15 @@ float Frame::frameProgress() return 1.f; } +float Frame::frameDuration() +{ + auto future = value().valid() ? handle() : nullptr; + if (future) + return future.duration(); + else + return -1.f; +} + void Frame::waitOnFrame() { auto future = value().valid() ? handle() : nullptr; diff --git a/sg/Frame.h b/sg/Frame.h index 16562453..eb7b45eb 100644 --- a/sg/Frame.h +++ b/sg/Frame.h @@ -26,6 +26,7 @@ namespace ospray { bool frameIsReady(); float frameProgress(); + float frameDuration(); void waitOnFrame(); void cancelFrame(); bool accumLimitReached(); diff --git a/sg/JSONDefs.h b/sg/JSONDefs.h index 481b7411..f3964e8c 100644 --- a/sg/JSONDefs.h +++ b/sg/JSONDefs.h @@ -103,6 +103,16 @@ inline void to_json(JSON &j, const Node &n) inline void from_json(const JSON &, Node &) {} +// Helper for converting ambiguous json types to stronger "subType" +#define CONVERT_TYPE(X) \ + { \ + if (j["subType"] == #X) { \ + n->setValue(X(n->valueAs<int>())); \ + if (n->hasMinMax()) \ + n->setMinMax(X(n->minAs<int>()), X(n->maxAs<int>())); \ + } \ + } + inline OSPSG_INTERFACE NodePtr createNodeFromJSON(const JSON &j) { NodePtr n = nullptr; @@ -150,17 +160,36 @@ inline OSPSG_INTERFACE NodePtr createNodeFromJSON(const JSON &j) { n->setMinMax(minMax[0], minMax[1]); } - // JSON doesn't distinguish the following types. - // Need conversion based on subType. + // JSON doesn't distinguish the following types. They are primitive type + // "int" and need conversion based on subType. + + // OSPRay enum types + CONVERT_TYPE(OSPAMRMethod); + CONVERT_TYPE(OSPCurveBasis); + CONVERT_TYPE(OSPCurveType); + CONVERT_TYPE(OSPDataType); + CONVERT_TYPE(OSPDeviceProperty); + CONVERT_TYPE(OSPError); + CONVERT_TYPE(OSPFrameBufferChannel); + CONVERT_TYPE(OSPFrameBufferFormat); + CONVERT_TYPE(OSPIntensityQuantity); + CONVERT_TYPE(OSPLogLevel); + CONVERT_TYPE(OSPPixelFilterType); + CONVERT_TYPE(OSPShutterType); + CONVERT_TYPE(OSPStereoMode); + CONVERT_TYPE(OSPSubdivisionMode); + CONVERT_TYPE(OSPSyncEvent); + CONVERT_TYPE(OSPTextureFilter); + CONVERT_TYPE(OSPTextureFormat); + CONVERT_TYPE(OSPUnstructuredCellType); + CONVERT_TYPE(OSPVolumeFilter); + CONVERT_TYPE(OSPVolumeFormat); // integer to uint8_t - if (j["subType"] == "uchar") { - n->setValue(uint8_t(n->valueAs<int>())); - if (n->hasMinMax()) - n->setMinMax(uint8_t(n->minAs<int>()), uint8_t(n->maxAs<int>())); - } + using uchar = uint8_t; + CONVERT_TYPE(uchar); - // vec2f to range1f + // vec2f to range1f - in json, these two are identical if (j["subType"] == "range1f") { vec2f v(n->valueAs<vec2f>()); n->setValue(math::range1f(v[0], v[1])); @@ -359,39 +388,55 @@ inline void from_json(const JSON &j, quaternionf &q) namespace utility { +template <typename T> +inline void captureType(JSON &j, const Any &a) +{ + if (a.is<T>()) + j = a.get<T>(); +} + inline void to_json(JSON &j, const Any &a) { - if (a.is<int>()) - j = a.get<int>(); - else if (a.is<bool>()) - j = a.get<bool>(); - else if (a.is<uint8_t>()) - j = a.get<uint8_t>(); - else if (a.is<uint32_t>()) - j = a.get<uint32_t>(); - else if (a.is<float>()) - j = a.get<float>(); - else if (a.is<std::string>()) - j = a.get<std::string>(); - else if (a.is<math::vec2i>()) - j = a.get<math::vec2i>(); - else if (a.is<math::vec2f>()) - j = a.get<math::vec2f>(); - else if (a.is<math::range1f>()) - j = a.get<math::range1f>(); - else if (a.is<math::vec3i>()) - j = a.get<math::vec3i>(); - else if (a.is<math::vec3f>()) - j = a.get<math::vec3f>(); - else if (a.is<math::vec4f>()) - j = a.get<math::vec4f>(); - else if (a.is<math::LinearSpace2f>()) - j = a.get<math::LinearSpace2f>(); - else if (a.is<math::AffineSpace3f>()) - j = a.get<math::AffineSpace3f>(); - else if (a.is<math::quaternionf>()) - j = a.get<math::quaternionf>(); - else { + j = {}; // start with empty + captureType<int>(j, a); + captureType<bool>(j, a); + captureType<uint8_t>(j, a); + captureType<uint32_t>(j, a); + captureType<float>(j, a); + captureType<std::string>(j, a); + captureType<math::vec2i>(j, a); + captureType<math::vec2f>(j, a); + captureType<math::range1f>(j, a); + captureType<math::vec3i>(j, a); + captureType<math::vec3f>(j, a); + captureType<math::vec4f>(j, a); + captureType<math::LinearSpace2f>(j, a); + captureType<math::AffineSpace3f>(j, a); + captureType<math::quaternionf>(j, a); + + // OSPRay enum types + captureType<OSPAMRMethod>(j, a); + captureType<OSPCurveBasis>(j, a); + captureType<OSPCurveType>(j, a); + captureType<OSPDataType>(j, a); + captureType<OSPDeviceProperty>(j, a); + captureType<OSPError>(j, a); + captureType<OSPFrameBufferChannel>(j, a); + captureType<OSPFrameBufferFormat>(j, a); + captureType<OSPIntensityQuantity>(j, a); + captureType<OSPLogLevel>(j, a); + captureType<OSPPixelFilterType>(j, a); + captureType<OSPShutterType>(j, a); + captureType<OSPStereoMode>(j, a); + captureType<OSPSubdivisionMode>(j, a); + captureType<OSPSyncEvent>(j, a); + captureType<OSPTextureFilter>(j, a); + captureType<OSPTextureFormat>(j, a); + captureType<OSPUnstructuredCellType>(j, a); + captureType<OSPVolumeFilter>(j, a); + captureType<OSPVolumeFormat>(j, a); + + if (j.is_null()) { std::cerr << "JSONDefs.h: :^) strikes back!!!" << std::endl; j = ":^)"; } @@ -399,7 +444,8 @@ inline void to_json(JSON &j, const Any &a) inline void from_json(const JSON &j, Any &a) { - if (j.is_primitive()) { // string, number , bool, null, or binary + if (j.is_primitive()) { // string, number , bool, null, or binary, basic types + // This will also include OSPRay enums, as ints if (j.is_null()) return; else if (j.is_boolean()) diff --git a/sg/Math.h b/sg/Math.h index 95174630..02b28957 100644 --- a/sg/Math.h +++ b/sg/Math.h @@ -99,7 +99,7 @@ inline LinearSpace3f getRotationMatrix(const LinearSpace3f &xfmM) { LinearSpace3f rot = xfmM; do { // compute next matrix rotNext in series - LinearSpace3f rotNext; + LinearSpace3f rotNext{one}; auto rotInvTranspose = rot.transposed().inverse(); for (int i = 0; i < 3; ++i) { diff --git a/sg/Mpi.h b/sg/Mpi.h index aa7ec38d..08e13202 100644 --- a/sg/Mpi.h +++ b/sg/Mpi.h @@ -83,6 +83,13 @@ inline int sgMpiWorldSize() return sgMPI.mpiWorldSize; } +inline void sgMpiBarrier() +{ +#ifdef USE_MPI + MPI_Barrier(MPI_COMM_WORLD); +#endif +} + inline bool compute_divisor(int x, int &divisor) { //Find the first half of possible divisors diff --git a/sg/Node.cpp b/sg/Node.cpp index b4ac3734..29ac8c65 100644 --- a/sg/Node.cpp +++ b/sg/Node.cpp @@ -279,7 +279,7 @@ namespace ospray { commit(); traverse<RenderScene>(); } - + box3f Node::bounds() { GetBounds visitor; @@ -420,7 +420,7 @@ namespace ospray { static bool libraryLoaded = false; if (!libraryLoaded) { // the anchor can be any symbol within this library, use nodeRegistry - loadLibrary("ospray_sg", reinterpret_cast<const void *>(&nodeRegistry)); + loadLibrary(reinterpret_cast<const void *>(&nodeRegistry), "ospray_sg"); libraryLoaded = true; } @@ -498,6 +498,27 @@ namespace ospray { OSP_REGISTER_SG_NODE_NAME(QuaternionfNode, quaternionf); OSP_REGISTER_SG_NODE_NAME(Linear2fNode, linear2f); + OSP_REGISTER_SG_NODE_NAME(OSPAMRMethodNode, OSPAMRMethod); + OSP_REGISTER_SG_NODE_NAME(OSPCurveBasisNode, OSPCurveBasis); + OSP_REGISTER_SG_NODE_NAME(OSPCurveTypeNode, OSPCurveType); + OSP_REGISTER_SG_NODE_NAME(OSPDataTypeNode, OSPDataType); + OSP_REGISTER_SG_NODE_NAME(OSPDevicePropertyNode, OSPDeviceProperty); + OSP_REGISTER_SG_NODE_NAME(OSPErrorNode, OSPError); + OSP_REGISTER_SG_NODE_NAME(OSPFrameBufferChannelNode, OSPFrameBufferChannel); + OSP_REGISTER_SG_NODE_NAME(OSPFrameBufferFormatNode, OSPFrameBufferFormat); + OSP_REGISTER_SG_NODE_NAME(OSPIntensityQuantityNode, OSPIntensityQuantity); + OSP_REGISTER_SG_NODE_NAME(OSPLogLevelNode, OSPLogLevel); + OSP_REGISTER_SG_NODE_NAME(OSPPixelFilterTypeNode, OSPPixelFilterType); + OSP_REGISTER_SG_NODE_NAME(OSPShutterTypeNode, OSPShutterType); + OSP_REGISTER_SG_NODE_NAME(OSPStereoModeNode, OSPStereoMode); + OSP_REGISTER_SG_NODE_NAME(OSPSubdivisionModeNode, OSPSubdivisionMode); + OSP_REGISTER_SG_NODE_NAME(OSPSyncEventNode, OSPSyncEvent); + OSP_REGISTER_SG_NODE_NAME(OSPTextureFilterNode, OSPTextureFilter); + OSP_REGISTER_SG_NODE_NAME(OSPTextureFormatNode, OSPTextureFormat); + OSP_REGISTER_SG_NODE_NAME(OSPUnstructuredCellTypeNode, OSPUnstructuredCellType); + OSP_REGISTER_SG_NODE_NAME(OSPVolumeFilterNode, OSPVolumeFilter); + OSP_REGISTER_SG_NODE_NAME(OSPVolumeFormatNode, OSPVolumeFormat); + // "filename" specialization allows differentiating purpose of string node. OSP_REGISTER_SG_NODE_NAME(StringNode, filename); OSP_REGISTER_SG_NODE_NAME(RGBNode, rgb); diff --git a/sg/Node.h b/sg/Node.h index cc5af11a..a68a0e3c 100644 --- a/sg/Node.h +++ b/sg/Node.h @@ -350,6 +350,28 @@ namespace sg { using QuaternionfNode = Node_T<quaternionf>; using Linear2fNode = Node_T<linear2f>; + // OSPRay enum types // + + using OSPAMRMethodNode = Node_T<OSPAMRMethod>; + using OSPCurveBasisNode = Node_T<OSPCurveBasis>; + using OSPCurveTypeNode = Node_T<OSPCurveType>; + using OSPDataTypeNode = Node_T<OSPDataType>; + using OSPDevicePropertyNode = Node_T<OSPDeviceProperty>; + using OSPErrorNode = Node_T<OSPError>; + using OSPFrameBufferChannelNode = Node_T<OSPFrameBufferChannel>; + using OSPFrameBufferFormatNode = Node_T<OSPFrameBufferFormat>; + using OSPIntensityQuantityNode = Node_T<OSPIntensityQuantity>; + using OSPLogLevelNode = Node_T<OSPLogLevel>; + using OSPPixelFilterTypeNode = Node_T<OSPPixelFilterType>; + using OSPShutterTypeNode = Node_T<OSPShutterType>; + using OSPStereoModeNode = Node_T<OSPStereoMode>; + using OSPSubdivisionModeNode = Node_T<OSPSubdivisionMode>; + using OSPSyncEventNode = Node_T<OSPSyncEvent>; + using OSPTextureFilterNode = Node_T<OSPTextureFilter>; + using OSPTextureFormatNode = Node_T<OSPTextureFormat>; + using OSPUnstructuredCellTypeNode = Node_T<OSPUnstructuredCellType>; + using OSPVolumeFilterNode = Node_T<OSPVolumeFilter>; + using OSPVolumeFormatNode = Node_T<OSPVolumeFormat>; // Extra aliases // diff --git a/sg/PluginCore.cpp b/sg/PluginCore.cpp index cd00f832..e08cea92 100644 --- a/sg/PluginCore.cpp +++ b/sg/PluginCore.cpp @@ -16,7 +16,7 @@ void * loadPluginCore(const std::string &name) { std::string libName = "ospray_studio_plugin_" + name; try { rkcommon::loadLibrary( - libName, reinterpret_cast<const void *>(&loadPluginCore)); + reinterpret_cast<const void *>(&loadPluginCore), libName); } catch (std::runtime_error &e) { std::cout << "...failed to load plugin '" << name << "'!" << " (plugin was not found). Please verify the name of the plugin" diff --git a/sg/camera/Camera.cpp b/sg/camera/Camera.cpp index 68edd597..9197c799 100644 --- a/sg/camera/Camera.cpp +++ b/sg/camera/Camera.cpp @@ -31,16 +31,16 @@ Camera::Camera(const std::string &type) child("motion blur").setMinMax(0.f, 1.f); createChild("shutterType", - "uchar", + "OSPShutterType", "type of shutter, for motion blur\n" " 0 = global\n" " 1 = rolling right\n" " 2 = rolling left\n" " 3 = rolling down\n" " 4 = rolling up", - uint8_t(OSP_SHUTTER_GLOBAL)); + OSP_SHUTTER_GLOBAL); child("shutterType") - .setMinMax(uint8_t(OSP_SHUTTER_GLOBAL), uint8_t(OSP_SHUTTER_ROLLING_UP)); + .setMinMax(OSP_SHUTTER_GLOBAL, OSP_SHUTTER_ROLLING_UP); createChild("rollingShutterDuration", "float", diff --git a/sg/camera/Panoramic.cpp b/sg/camera/Panoramic.cpp index 4b91c018..32dedb19 100644 --- a/sg/camera/Panoramic.cpp +++ b/sg/camera/Panoramic.cpp @@ -19,9 +19,9 @@ namespace ospray { 0.0635f); child("interpupillaryDistance").setMinMax(0.f, 0.1f); createChild("stereoMode", - "int", + "OSPStereoMode", "0=none, 1=left, 2=right, 3=side-by-side, 4=top-bottom", - 0); + OSP_STEREO_NONE); } OSP_REGISTER_SG_NODE_NAME(Panoramic, camera_panoramic); diff --git a/sg/camera/Perspective.cpp b/sg/camera/Perspective.cpp index ec96032d..8634eed3 100644 --- a/sg/camera/Perspective.cpp +++ b/sg/camera/Perspective.cpp @@ -33,9 +33,9 @@ Perspective::Perspective() : Camera("perspective") "vertical edges are projected to be parallel", false); createChild("stereoMode", - "int", + "OSPStereoMode", "[0=none, 1=left, 2=right, 3=side-by-side, 4=top-bottom]", - 0); + OSP_STEREO_NONE); createChild("interpupillaryDistance", "float", "Distance between left and right eye for stereo mode [default 0.0635]", @@ -45,7 +45,7 @@ Perspective::Perspective() : Camera("perspective") child("apertureRadius").setMinMax(0.f, 5.f); // XXX set these based on child("focusDistance").setMinMax(1.f, 1e6f); // world size child("stereoMode") - .setMinMax((int)OSP_STEREO_NONE, (int)OSP_STEREO_TOP_BOTTOM); + .setMinMax(OSP_STEREO_NONE, OSP_STEREO_TOP_BOTTOM); child("interpupillaryDistance").setMinMax(0.f, 0.1f); child("aspect").setReadOnly(); diff --git a/sg/generator/Torus.cpp b/sg/generator/Torus.cpp index e6f6faef..4064fe29 100644 --- a/sg/generator/Torus.cpp +++ b/sg/generator/Torus.cpp @@ -70,7 +70,6 @@ void Torus::generateData() }); auto volume = createNode("torus", "structuredRegular"); - volume->createChild("voxelType", "int", int(OSP_FLOAT)); volume->createChild("gridOrigin", "vec3f", vec3f(-0.5f)); volume->createChild("gridSpacing", "vec3f", vec3f(1.f / size)); // The "true" flag shares data with OSPRay rather than copying. diff --git a/sg/generator/UnstructuredVol.cpp b/sg/generator/UnstructuredVol.cpp index d0e9736c..07745de1 100644 --- a/sg/generator/UnstructuredVol.cpp +++ b/sg/generator/UnstructuredVol.cpp @@ -25,7 +25,7 @@ OSP_REGISTER_SG_NODE_NAME(UnstructuredVol, generator_unstructured_volume); UnstructuredVol::UnstructuredVol() { auto ¶meters = child("parameters"); - parameters.sgOnly(); + parameters.setSGOnly(); // define hexahedron parameters parameters.createChild("hSize", "float", .4f); @@ -166,7 +166,7 @@ void UnstructuredVol::generateData() std::vector<uint32_t> cells = {0, 8, 14, 18}; // define cell types - std::vector<uint8_t> cellTypes = { + std::vector<OSPUnstructuredCellType> cellTypes = { OSP_HEXAHEDRON, OSP_WEDGE, OSP_TETRAHEDRON, OSP_PYRAMID}; auto &volume = tf.createChild("unstructured_volume", "volume_unstructured"); diff --git a/sg/generator/WaveletVolume.cpp b/sg/generator/WaveletVolume.cpp index 7e240000..80a0f5e9 100644 --- a/sg/generator/WaveletVolume.cpp +++ b/sg/generator/WaveletVolume.cpp @@ -101,7 +101,6 @@ void WaveletVolume::generateData() } }); - volume.createChild("voxelType") = int(OSP_FLOAT); volume.createChild("gridOrigin", "vec3f", brick_ghostBounds.lower); volume.createChild("gridSpacing", "vec3f", gridSpacing); volume.createChildData("data", brick_ghostDims, 0, voxels.data()); @@ -130,7 +129,6 @@ void WaveletVolume::generateData() } }); - volume.createChild("voxelType") = int(OSP_FLOAT); volume.createChild("gridOrigin", "vec3f", gridOrigin); volume.createChild("gridSpacing", "vec3f", gridSpacing); volume.createChildData("data", dimensions, 0, voxels.data()); diff --git a/sg/importer/Importer.h b/sg/importer/Importer.h index f9455b83..c543828b 100644 --- a/sg/importer/Importer.h +++ b/sg/importer/Importer.h @@ -132,7 +132,6 @@ struct OSPSG_INTERFACE Importer : public Node protected: rkcommon::FileName fileName; std::shared_ptr<sg::MaterialRegistry> materialRegistry = nullptr; - // std::vector<NodePtr> *cameras = nullptr; std::shared_ptr<CameraMap> cameras{nullptr}; std::vector<sg::Animation> *animations = nullptr; NodePtr volumeParams; @@ -151,7 +150,7 @@ extern OSPSG_INTERFACE std::map<std::string, std::string> importerMap; // Providing a unique transform instance as root to add existing imported model to, // should probably be the responsibility of the calling routine inline std::shared_ptr<Importer> getImporter( - NodePtr root, rkcommon::FileName fileName) + NodePtr root, rkcommon::FileName fileName, bool reloadAsset = false) { // Get the absolute path to the file for use in AssetsCatalogue rkcommon::FileName fullName = fileName.canonical(); @@ -165,11 +164,24 @@ inline std::shared_ptr<Importer> getImporter( std::string importer = fnd->second; std::string nodeName; - if (cat.find(fullName) != cat.end()) { + if (cat.find(fullName) != cat.end() && cat[fullName].lock()) { // Importer node and its rootXfm auto origNode = cat[fullName].lock(); std::string rootXfmName = baseName + "_rootXfm"; + // Only instance assets that have a rootXfm, otherwise just reload them. + // Interested in instancing mesh data, not pure lights files + // Or, if origNode is gone, the asset was deleted and needs to be reloaded. + if (!origNode->hasChild(rootXfmName)) + reloadAsset = true; + + // If reloading asset, simply return the original importer node + if (reloadAsset) { + std::cout << "Reloading: " << fullName << " as " << origNode->name() + << std::endl; + return origNode->nodeAs<Importer>(); + } + // Existing import, instance it! std::cout << "Instancing: " << fullName << " as " << origNode->name() << std::endl; diff --git a/sg/importer/OBJ.cpp b/sg/importer/OBJ.cpp index 27ce8139..05daf879 100644 --- a/sg/importer/OBJ.cpp +++ b/sg/importer/OBJ.cpp @@ -96,6 +96,9 @@ namespace ospray { } else if (floats.size() == 3) { paramType = "vec3f"; paramValue = vec3f(floats[0], floats[1], floats[2]); + } else if (floats.size() == 4) { + paramType = "linear2f"; + paramValue = linear2f(floats[0], floats[1], floats[2], floats[3]); } else { // Unknown type. paramValue = typeAndValueString; @@ -369,7 +372,8 @@ namespace ospray { // Create a root Transform/Instance off the Importer, under which to build // the import hierarchy std::string baseName = fileName.name() + "_rootXfm"; - auto rootNode = createNode(baseName, "transform"); + NodePtr rootNode = hasChild(baseName) ? child(baseName).nodeAs<Node>() + : createNode(baseName, "transform"); auto objData = loadFromFile(fileName); @@ -378,7 +382,18 @@ namespace ospray { if (materialNodes.empty()) materialNodes.emplace_back(createNode("default", "obj")); - size_t baseMaterialOffset = materialRegistry->baseMaterialOffSet(); + // Create a child under the importer to hold the baseMaterialOffset + // used when the asset is reloaded, to keep the same material indices + uint32_t baseMaterialOffset = materialRegistry->baseMaterialOffSet(); + static std::string bmo = "baseMaterialOffset"; + if (hasChild(bmo)) { + baseMaterialOffset = child(bmo).valueAs<uint32_t>(); + } else { + createChild(bmo, "uint32_t", baseMaterialOffset); + child(bmo).setReadOnly(); + child(bmo).setSGOnly(); + child(bmo).setSGNoUI(); + } for (auto m : materialNodes) materialRegistry->add(m); diff --git a/sg/importer/PCD.cpp b/sg/importer/PCD.cpp index db062ec0..e64a011c 100644 --- a/sg/importer/PCD.cpp +++ b/sg/importer/PCD.cpp @@ -570,6 +570,7 @@ int readPCDBodyBinary(const FileName &fileName, PCDData &pcdData) "[PCDImporter::readBinary] Size of decompressed lzf data (%u) does not match value stored in PCD header (%u).\n", tmpSize, uncompSize); + delete[] map; return (-1); } /* diff --git a/sg/importer/glTF.cpp b/sg/importer/glTF.cpp index d53188df..311dac8b 100644 --- a/sg/importer/glTF.cpp +++ b/sg/importer/glTF.cpp @@ -21,7 +21,7 @@ #define DEBUG if (verboseImport) std::cout << prefix << "(D): " #define INFO if (verboseImport) std::cout << prefix << "(I): " -#define WARN std::cout << prefix << "(W): " +#define WARN if (verboseImport) std::cout << prefix << "(W): " #define ERR std::cerr << prefix << "(E): " namespace ospray { @@ -89,6 +89,10 @@ struct GLTFData volumeParams = _volumeParams; } + void setBaseMaterialOffset(uint32_t offset) { + baseMaterialOffset = offset; + } + private: bool verboseImport{false}; // Enable/disable import logging InstanceConfiguration ic; @@ -108,7 +112,7 @@ struct GLTFData std::vector<NodePtr> ospMaterials; - size_t baseMaterialOffset = 0; // set in createMaterials() + uint32_t baseMaterialOffset = 0; int numIntelLights{0}; void loadKeyframeInput(int accessorID, std::vector<float> &kfInput); @@ -207,7 +211,6 @@ bool GLTFData::parseAsset() if (!asset.extensions.empty()) INFO << " Extensions Listed:\n"; - // XXX Warn on any extensions used if (!model.extensionsUsed.empty()) { WARN << " ExtensionsUsed:\n"; for (const auto &ext : model.extensionsUsed) @@ -219,7 +222,6 @@ bool GLTFData::parseAsset() WARN << " " << ext << "\n"; } - // XXX INFO << "... " << model.accessors.size() << " accessors\n"; INFO << "... " << model.animations.size() << " animations\n"; INFO << "... " << model.buffers.size() << " buffers\n"; @@ -285,12 +287,14 @@ void GLTFData::loadNodeInfo(const int nid, NodePtr sgNode) isVolume = refLink.Get("type").Get<std::string>() == "volume"; } - auto node = n.extensions.find("BIT_node_info")->second; - if (node.Has("id")) { - auto &nodeId = node.Get("id").Get<std::string>(); - if (!isValidUUIDv4(nodeId)) - std::cerr << nodeId << " is not a valid version 4 UUID\n"; - sgNode->createChild("instanceId", "string", nodeId); + if (n.extensions.find("BIT_node_info") != n.extensions.end()) { + auto node = n.extensions.find("BIT_node_info")->second; + if (node.Has("id")) { + auto &nodeId = node.Get("id").Get<std::string>(); + if (!isValidUUIDv4(nodeId)) + std::cerr << nodeId << " is not a valid version 4 UUID\n"; + sgNode->createChild("instanceId", "string", nodeId); + } } // nothing to import @@ -377,8 +381,9 @@ void GLTFData::createLightTemplates() // KHR_lights_punctual for (auto &l : model.lights) { static auto nLight = 0; + // Only add light number if name is otherwise empty. auto lightName = - l.name != "" ? l.name : "light_" + std::to_string(nLight++); + l.name != "" ? l.name : ("light_" + std::to_string(nLight++)); auto lightType = l.type; NodePtr newLight; @@ -411,8 +416,11 @@ void GLTFData::createLightTemplates() lightColor = rgb{(float)l.color[0], (float)l.color[1], (float)l.color[2]}; newLight->child("color") = lightColor; + // glTF specifies intensity in lux, OSPRay in Watts + // By industry convention, at 100% efficiency 1 watt of electrical power + // produces 683 lumens. Convert to watts for OSPRay parameter. if (l.intensity) - newLight->child("intensity") = (float)l.intensity; + newLight->child("intensity") = (float)l.intensity / 683.f; if (l.range) WARN << "Range value for light is not supported yet" << std::endl; @@ -440,7 +448,6 @@ void GLTFData::createMaterials() ospMaterials.push_back(createOSPMaterial(material)); } - baseMaterialOffset = materialRegistry->baseMaterialOffSet(); for (auto m : ospMaterials) materialRegistry->add(m); } @@ -782,7 +789,8 @@ void GLTFData::visitNode(NodePtr sgNode, // create child animate camera for all camera nodes added to scene hierarchy, // bool value is set during createAnimation when appropriate target xfm is // found - if (n.camera != -1 && !importCameras && cameras) { + if (n.camera != -1 && !importCameras && cameras + && cameras->contains(n.name)) { // add camera from existing .sg cameras auto camera = cameras->at(n.name); newXfm->add(camera); @@ -799,8 +807,9 @@ void GLTFData::visitNode(NodePtr sgNode, camera->child(c.first).setSGOnly(); } } + // Only add camera number if name is otherwise empty. auto uniqueCamName = - n.name != "" ? n.name : "camera_" + std::to_string(nCamera); + n.name != "" ? n.name : ("camera_" + std::to_string(nCamera)); camera->child("uniqueCameraName") = uniqueCamName; camera->child("cameraId").setValue(++nCamera); @@ -832,11 +841,8 @@ void GLTFData::visitNode(NodePtr sgNode, for (auto &lightIdx : lightIdxs) { auto lightTemplate = lightTemplates[lightIdx]; - static int lightCounter = 0; // instantiate SG light nodes - auto uniqueLightName = n.name != "" - ? n.name + std::to_string(lightCounter++) - : lightTemplate->name() + std::to_string(lightCounter++); + auto uniqueLightName = n.name != "" ? n.name : lightTemplate->name(); auto light = createNode(uniqueLightName, lightTemplate->subType()); for (auto &c : lightTemplate->children()) { if (light->hasChild(c.first)) @@ -1144,13 +1150,11 @@ NodePtr GLTFData::createOSPMesh( ospGeom->createChildData("sphere.texcoord", ospGeom->vt, true); } - if (ospGeom) { - // add one for default, "no material" material - auto materialID = prim.material + 1 + baseMaterialOffset; - ospGeom->mIDs.resize(ospGeom->skinnedPositions.size(), materialID); - ospGeom->createChildData("material", ospGeom->mIDs, true); - ospGeom->child("material").setSGOnly(); - } + // add one for default, "no material" material + auto materialID = prim.material + 1 + baseMaterialOffset; + ospGeom->mIDs.resize(ospGeom->skinnedPositions.size(), materialID); + ospGeom->createChildData("material", ospGeom->mIDs, true); + ospGeom->child("material").setSGOnly(); return ospGeom; } @@ -1736,6 +1740,8 @@ NodePtr GLTFData::createOSPTexture(const std::string &texParam, if (ospTex.checkForUDIM(img.name)) img.image.clear(); + ospTex.params.flip = false; // glTF textures are not vertically flipped + // Pre-loaded texture image (loaded by tinygltf) if (!img.image.empty()) { ospTex.params.size = vec2ul(img.width, img.height); @@ -1751,8 +1757,6 @@ NodePtr GLTFData::createOSPTexture(const std::string &texParam, } else { // Load texture from file (external uri or udim tiles) - ospTex.params.flip = false; // glTF textures are not vertically flipped - // use same path as gltf scene file // If load fails, remove the texture node if (!ospTex.load(img.name, @@ -1860,7 +1864,8 @@ void glTFImporter::importScene() // Create a root Transform/Instance off the Importer, under which to build // the import hierarchy std::string baseName = fileName.name() + "_rootXfm"; - auto rootNode = createNode(baseName, "transform"); + NodePtr rootNode = hasChild(baseName) ? child(baseName).nodeAs<Node>() + : createNode(baseName, "transform"); GLTFData gltf(rootNode, fileName, @@ -1875,7 +1880,22 @@ void glTFImporter::importScene() return; gltf.setScheduler(scheduler); gltf.setVolumeParams(volumeParams); - gltf.createMaterials(); + if (materialRegistry) { + // Create a child under the importer to hold the baseMaterialOffset + // used when the asset is reloaded, to keep the same material indices + uint32_t offset = materialRegistry->baseMaterialOffSet(); + static std::string bmo = "baseMaterialOffset"; + if (hasChild(bmo)) { + offset = child(bmo).valueAs<uint32_t>(); + } else { + createChild(bmo, "uint32_t", offset); + child(bmo).setReadOnly(); + child(bmo).setSGOnly(); + child(bmo).setSGNoUI(); + } + gltf.setBaseMaterialOffset(offset); + gltf.createMaterials(); + } gltf.createLightTemplates(); if (importCameras) { diff --git a/sg/renderer/Renderer.cpp b/sg/renderer/Renderer.cpp index 87e4895d..d118ba74 100644 --- a/sg/renderer/Renderer.cpp +++ b/sg/renderer/Renderer.cpp @@ -24,10 +24,10 @@ Renderer::Renderer(std::string type) "transparent background color and alpha (RGBA), if no map_backplate set", rgba(vec3f(0.f), 1.f)); // black, with opaque alpha createChild("pixelFilter", - "int", + "OSPPixelFilterType", "pixel filter used by the renderer for antialiasing\n" "(0=point, 1=box, 2=gauss, 3=mitchell, 4=blackman_harris)", - (int)pixelFilter); + pixelFilter); child("type").setSGNoUI(); child("type").setSGOnly(); @@ -36,7 +36,8 @@ Renderer::Renderer(std::string type) child("maxPathLength").setMinMax(0, 1000); child("minContribution").setMinMax(0.f, 10.f); child("varianceThreshold").setMinMax(0.f, 100.f); - child("pixelFilter").setMinMax(0, 4); + child("pixelFilter").setMinMax(OSP_PIXELFILTER_POINT, + OSP_PIXELFILTER_BLACKMAN_HARRIS); setHandle(cpp::Renderer(child("type").valueAs<std::string>())); } diff --git a/sg/renderer/Renderer.h b/sg/renderer/Renderer.h index 2e60c6be..f13188ad 100644 --- a/sg/renderer/Renderer.h +++ b/sg/renderer/Renderer.h @@ -16,7 +16,7 @@ struct OSPSG_INTERFACE Renderer NodeType type() const override; - OSPPixelFilterTypes pixelFilter{OSP_PIXELFILTER_GAUSS}; + OSPPixelFilterType pixelFilter{OSP_PIXELFILTER_GAUSS}; }; } // namespace sg diff --git a/sg/scene/geometry/Curves.cpp b/sg/scene/geometry/Curves.cpp index a3cd457b..bc4c88cc 100644 --- a/sg/scene/geometry/Curves.cpp +++ b/sg/scene/geometry/Curves.cpp @@ -21,8 +21,8 @@ Curves::Curves() : Geometry("curve") createChildData("vertex.position_radius", std::vector<vec4f>( {vec4f(-1.f, -1.f, -1.f, 1.f), vec4f(1.f, 1.f, 1.f, 1.f)})); - createChild("type", "uchar", (uint8_t)OSP_ROUND); - createChild("basis", "uchar", (uint8_t)OSP_LINEAR); + createChild("type", "OSPCurveType", OSP_ROUND); + createChild("basis", "OSPCurveBasis", OSP_LINEAR); } } // namespace sg } // namespace ospray diff --git a/sg/scene/lights/AmbientLight.cpp b/sg/scene/lights/AmbientLight.cpp index b0127334..ff55940b 100644 --- a/sg/scene/lights/AmbientLight.cpp +++ b/sg/scene/lights/AmbientLight.cpp @@ -20,8 +20,7 @@ AmbientLight::AmbientLight() : Light("ambient") { // Ambient should be invisible by default, not directly viewable child("visible").setValue(false); - child("intensityQuantity") - .setValue(uint8_t(OSP_INTENSITY_QUANTITY_IRRADIANCE)); + child("intensityQuantity").setValue(OSP_INTENSITY_QUANTITY_IRRADIANCE); } } // namespace sg diff --git a/sg/scene/lights/CylinderLight.cpp b/sg/scene/lights/CylinderLight.cpp index f3934f61..a83351f3 100644 --- a/sg/scene/lights/CylinderLight.cpp +++ b/sg/scene/lights/CylinderLight.cpp @@ -28,7 +28,7 @@ CylinderLight::CylinderLight() : Light("cylinder") vec3f(0.f, 0.f, 1.f)); createChild("radius", "float", "radius of the cylinder", 1.f); - child("intensityQuantity").setValue(uint8_t(OSP_INTENSITY_QUANTITY_RADIANCE)); + child("intensityQuantity").setValue(OSP_INTENSITY_QUANTITY_RADIANCE); } } // namespace sg diff --git a/sg/scene/lights/DirectionalLight.cpp b/sg/scene/lights/DirectionalLight.cpp index ead51244..1af0113c 100644 --- a/sg/scene/lights/DirectionalLight.cpp +++ b/sg/scene/lights/DirectionalLight.cpp @@ -25,8 +25,7 @@ DirectionalLight::DirectionalLight() : Light("distant") "apparent size (in degrees) [default 0.53° ~sun]", 0.53f); - child("intensityQuantity") - .setValue(uint8_t(OSP_INTENSITY_QUANTITY_IRRADIANCE)); + child("intensityQuantity").setValue(OSP_INTENSITY_QUANTITY_IRRADIANCE); child("direction").setMinMax(-1.f, 1.f); // per component min/max child("angularDiameter").setMinMax(0.f, 10.f); diff --git a/sg/scene/lights/HDRILight.cpp b/sg/scene/lights/HDRILight.cpp index a2407e4a..e9360dc7 100644 --- a/sg/scene/lights/HDRILight.cpp +++ b/sg/scene/lights/HDRILight.cpp @@ -13,10 +13,15 @@ struct OSPSG_INTERFACE HDRILight : public Light virtual ~HDRILight() override = default; void preCommit() override; void postCommit() override; + + private: + std::shared_ptr<Texture2D> defaultMapPtr; }; OSP_REGISTER_SG_NODE_NAME(HDRILight, hdri); +static std::weak_ptr<ospray::sg::Texture2D> staticDefaultMap; + // HDRILight definitions ///////////////////////////////////////////// HDRILight::HDRILight() : Light("hdri") @@ -33,11 +38,39 @@ HDRILight::HDRILight() : Light("hdri") "direction to which the center of the texture will be mapped", vec3f(0.f, 0.f, 1.f)); - child("intensityQuantity") = uint8_t(OSP_INTENSITY_QUANTITY_SCALE); + child("intensityQuantity") = OSP_INTENSITY_QUANTITY_SCALE; child("intensityQuantity").setReadOnly(); child("up").setMinMax(-1.f, 1.f); // per component min/max child("direction").setMinMax(-1.f, 1.f); // per component min/max + + // Create the default map, only once + if (staticDefaultMap.lock()) { + defaultMapPtr = staticDefaultMap.lock(); + } else { + // clang-format off + static uint32_t checker[] = { + 0x7f007f00, 0x7f007f00, 0x7f007f00, 0x7f007f00, + 0x007f007f, 0x007f007f, 0x007f007f, 0x007f007f, + 0x7f007f00, 0x7f007f00, 0x7f007f00, 0x7f007f00, + 0x007f007f, 0x007f007f, 0x007f007f, 0x007f007f, + 0x7f007f00, 0x7f007f00, 0x7f007f00, 0x7f007f00, + 0x007f007f, 0x007f007f, 0x007f007f, 0x007f007f, + 0x7f007f00, 0x7f007f00, 0x7f007f00, 0x7f007f00, + 0x007f007f, 0x007f007f, 0x007f007f, 0x007f007f}; + // clang-format on + defaultMapPtr = createNodeAs<Texture2D>("map", "texture_2d"); + staticDefaultMap = defaultMapPtr; + Texture2D &defaultMap = *defaultMapPtr; + defaultMap.params.size = vec2ul(16, 8); + defaultMap.params.components = 1; + defaultMap.params.depth = 1; + // preferLinear = false creates an L8 texture, rather than R8 + if (!defaultMap.load("_defaultHDRI", false, true, 4, checker)) + std::cerr << "!!!! Default HDRI texture failed!" << std::endl; + // Set filename to read-only to prevent user removing it via UI + defaultMap["filename"].setReadOnly(); + } } void HDRILight::preCommit() @@ -46,23 +79,30 @@ void HDRILight::preCommit() auto filename = child("filename").valueAs<std::string>(); + // defaultMap is a fallback if there is no other map loaded + defaultMapPtr = staticDefaultMap.lock(); + Texture2D &defaultMap = *defaultMapPtr; + // Load HDRI file and create texture if (filename == "") { - remove("map"); + add(defaultMap); } else { auto mapFilename = hasChild("map") ? child("map")["filename"].valueAs<std::string>() : ""; // reload or remove if HDRI filename changes if (filename != mapFilename) { - // Remove texture if had a map, but mapFilename has been removed - if (hasChild("map") && mapFilename == "") { - remove("map"); - child("filename") = std::string(""); + // If map has changed, update HDRI filename + if (hasChild("map") && child("map").isModified()) { + child("filename") = mapFilename; + // Remove texture if had a map, but mapFilename has been removed + if (mapFilename == "") + add(defaultMap); } else { + // Otherwise, create/replace map and load HDRI filename auto &hdriTex = createChild("map", "texture_2d"); auto texture = hdriTex.nodeAs<sg::Texture2D>(); if (!texture->load(filename, false, false)) { - remove("map"); + add(defaultMap); child("filename") = std::string(""); } } @@ -78,8 +118,7 @@ void HDRILight::postCommit() auto &map = child("map").valueAs<cpp::Texture>(); asLight.setParam("map", (cpp::Texture)map); map.commit(); - } else - asLight.removeParam("map"); + } Light::postCommit(); } diff --git a/sg/scene/lights/Light.cpp b/sg/scene/lights/Light.cpp index fd634dcf..047dc8f5 100644 --- a/sg/scene/lights/Light.cpp +++ b/sg/scene/lights/Light.cpp @@ -20,7 +20,7 @@ Light::Light(std::string type) // Default unknown here because light type determines default createChild("intensityQuantity", - "uchar", + "OSPIntensityQuantity", "type of the value represented by a light's `intensity` parameter\n" " 0 = radiance (W/sr/m^2)\n" " 1 = irradiance (W/m^2)\n" @@ -28,14 +28,13 @@ Light::Light(std::string type) " 3 = power (W)\n" " 4 = scale, linear scaling factor for light sources with a built-in quantity\n" " (e.g., `HDRI`, or `sunSky`, or when using `intensityDistribution`)", - uint8_t(OSP_INTENSITY_QUANTITY_UNKNOWN)); + OSP_INTENSITY_QUANTITY_UNKNOWN); createChild("type", "string", "OSPRay light type", type).setReadOnly(); child("intensity").setMinMax(0.f, 10.f); child("intensityQuantity") - .setMinMax(uint8_t(OSP_INTENSITY_QUANTITY_RADIANCE), - uint8_t(OSP_INTENSITY_QUANTITY_SCALE)); + .setMinMax(OSP_INTENSITY_QUANTITY_RADIANCE, OSP_INTENSITY_QUANTITY_SCALE); child("type").setSGOnly(); child("enable").setSGOnly(); @@ -72,7 +71,7 @@ void Light::preCommit() if (lamp.load()) { // When using intensityDistribution, SCALE is the only supported // quantity - child("intensityQuantity") = uint8_t(OSP_INTENSITY_QUANTITY_SCALE); + child("intensityQuantity") = OSP_INTENSITY_QUANTITY_SCALE; createChildData("intensityDistribution", lamp.lid); // Set c0 if iSym = 0 (asymmetric) #if 0 // XXX Set it to what exactly? Default is already perpendicular diff --git a/sg/scene/lights/LightsManager.cpp b/sg/scene/lights/LightsManager.cpp index 03707237..e420a6f9 100644 --- a/sg/scene/lights/LightsManager.cpp +++ b/sg/scene/lights/LightsManager.cpp @@ -28,8 +28,12 @@ bool LightsManager::lightExists(std::string name) // Add a light node (main entry) bool LightsManager::addLight(NodePtr light) { - if (lightExists(light->name())) + if (lightExists(light->name())) { + // if light exists, just update its parameters + for (auto ¶m : light->children()) + light->add(param.second); return false; + } // remove default light if (hasChild("default-ambient") && rmDefaultLight) diff --git a/sg/scene/lights/PointLight.cpp b/sg/scene/lights/PointLight.cpp index 1c7f6edf..c2f88327 100644 --- a/sg/scene/lights/PointLight.cpp +++ b/sg/scene/lights/PointLight.cpp @@ -28,8 +28,7 @@ PointLight::PointLight() : Light("sphere") "main orientation of `intensityDistribution`", vec3f(0.f, 0.f, 1.f)).setMinMax(-1.f, 1.f); - child("intensityQuantity") - .setValue(uint8_t(OSP_INTENSITY_QUANTITY_INTENSITY)); + child("intensityQuantity").setValue(OSP_INTENSITY_QUANTITY_INTENSITY); // PointLight supports a photometric measuredSource addMeasuredSource(); diff --git a/sg/scene/lights/QuadLight.cpp b/sg/scene/lights/QuadLight.cpp index 3486ada2..8ec698b5 100644 --- a/sg/scene/lights/QuadLight.cpp +++ b/sg/scene/lights/QuadLight.cpp @@ -22,7 +22,7 @@ QuadLight::QuadLight() : Light("quad") createChild("edge1", "vec3f", vec3f(1.f, 0.f, 0.f)); createChild("edge2", "vec3f", vec3f(0.f, 1.f, 0.f)); - child("intensityQuantity").setValue(uint8_t(OSP_INTENSITY_QUANTITY_RADIANCE)); + child("intensityQuantity").setValue(OSP_INTENSITY_QUANTITY_RADIANCE); // QuadLight supports a photometric measuredSource addMeasuredSource(); diff --git a/sg/scene/lights/SpotLight.cpp b/sg/scene/lights/SpotLight.cpp index ceeafe76..4212a7b4 100644 --- a/sg/scene/lights/SpotLight.cpp +++ b/sg/scene/lights/SpotLight.cpp @@ -39,8 +39,7 @@ SpotLight::SpotLight() : Light("spot") createChild("radius", "float", 0.f); createChild("innerRadius", "float", 0.f); - child("intensityQuantity") - .setValue(uint8_t(OSP_INTENSITY_QUANTITY_INTENSITY)); + child("intensityQuantity").setValue(OSP_INTENSITY_QUANTITY_INTENSITY); child("direction").setMinMax(-1.f, 1.f); // per component min/max child("openingAngle").setMinMax(0.f, 180.f); diff --git a/sg/scene/lights/SunSky.cpp b/sg/scene/lights/SunSky.cpp index 4688fa85..c89fa918 100644 --- a/sg/scene/lights/SunSky.cpp +++ b/sg/scene/lights/SunSky.cpp @@ -45,7 +45,7 @@ SunSky::SunSky() : Light("sunSky") "fraction of the lower hemisphere to cover [0-1]", 0.01f); - child("intensityQuantity") = (uint8_t)OSP_INTENSITY_QUANTITY_SCALE; + child("intensityQuantity") = OSP_INTENSITY_QUANTITY_SCALE; child("intensityQuantity").setReadOnly(); // Set reasonable limits, this will set slider range diff --git a/sg/scene/volume/Vdb.cpp b/sg/scene/volume/Vdb.cpp index f3190167..bb4f2df2 100644 --- a/sg/scene/volume/Vdb.cpp +++ b/sg/scene/volume/Vdb.cpp @@ -229,7 +229,8 @@ namespace ospray { // Query VDB voxel value range and set volume range range1f valueRange; - vdb->evalMinMax(valueRange.lower, valueRange.upper); + openvdb::math::MinMax<float> minMax = openvdb::tools::minMax(vdb->tree()); + valueRange = range1f(minMax.min(), minMax.max()); child("value") = valueRange; } #endif //USE_OPENVDB diff --git a/sg/scene/volume/Volume.cpp b/sg/scene/volume/Volume.cpp index d6c90a87..5384e73c 100644 --- a/sg/scene/volume/Volume.cpp +++ b/sg/scene/volume/Volume.cpp @@ -13,7 +13,12 @@ Volume::Volume(const std::string &osp_type) "bool", "enable affects whether the object exists in the world", true); - createChild("filter", "int", "0 = nearest, 100 = trilinear", 0); + createChild("filter", + "OSPVolumeFilter", + "0 = nearest,\n" + "100 = linear\n" + "200 = cubic", + OSP_VOLUME_FILTER_NEAREST); createChild("densityScale", "float", "makes volumes uniformly thinner or thicker\n" @@ -65,7 +70,7 @@ void Volume::load(const FileName &fileNameAbs) } if (!fileLoaded) { - auto &voxelType = child("voxelType").valueAs<int>(); + auto &voxelDataType = child("voxelType").valueAs<OSPDataType>(); FileName realFileName = fileNameAbs; FILE *file = fopen(realFileName.c_str(), "rb"); @@ -73,7 +78,6 @@ void Volume::load(const FileName &fileNameAbs) throw std::runtime_error( "Volume::load : could not open file '" + realFileName.str()); } - OSPDataType voxelDataType = (OSPDataType)voxelType; switch (voxelDataType) { case OSP_UCHAR: diff --git a/sg/scene/volume/Volume.h b/sg/scene/volume/Volume.h index 0d2d7dde..5b07809f 100644 --- a/sg/scene/volume/Volume.h +++ b/sg/scene/volume/Volume.h @@ -24,12 +24,12 @@ struct OSPSG_INTERFACE VolumeParams : public Node VolumeParams(bool structured) { if (structured) { - createChild("voxelType", "int", int(OSP_FLOAT)); + createChild("voxelType", "OSPDataType", OSP_FLOAT); createChild("dimensions", "vec3i", vec3i(18, 25, 18)); createChild("gridOrigin", "vec3f", vec3f(-1.f)); createChild("gridSpacing", "vec3f", vec3f(2.f / 100)); } else { - createChild("voxelType", "int", int(OSP_FLOAT)); + createChild("voxelType", "OSPDataType", OSP_FLOAT); createChild("dimensions", "vec3i", vec3i(180, 180, 180)); createChild("gridOrigin", "vec3f", vec3f(0)); createChild("gridSpacing", "vec3f", vec3f(1, 1, 1)); diff --git a/sg/scene/volume/VolumeTimeStep.h b/sg/scene/volume/VolumeTimeStep.h index 6e9e389a..b1fd1cfd 100644 --- a/sg/scene/volume/VolumeTimeStep.h +++ b/sg/scene/volume/VolumeTimeStep.h @@ -26,7 +26,7 @@ namespace ospray { struct VolumeTimestep { VolumeTimestep(const std::string &filename, - const int &voxelType, + const OSPDataType &voxelType, const vec3i &dimensions, const vec3f &gridOrigin, const vec3f &gridSpacing) @@ -98,7 +98,7 @@ namespace ospray { sgVolume->createChild("dimensions", "vec3i", dimensions); sgVolume->createChild("gridOrigin", "vec3f", gridOrigin); sgVolume->createChild("gridSpacing", "vec3f", gridSpacing); - sgVolume->createChild("voxelType", "int", voxelType); + sgVolume->createChild("voxelType", "OSPDataType", voxelType); fileLoaded = true; } @@ -107,7 +107,7 @@ namespace ospray { } std::string filename; - int voxelType; + OSPDataType voxelType; vec3i dimensions; vec3f gridOrigin; vec3f gridSpacing; diff --git a/sg/texture/Texture2D.cpp b/sg/texture/Texture2D.cpp index e34ef92b..b2926647 100644 --- a/sg/texture/Texture2D.cpp +++ b/sg/texture/Texture2D.cpp @@ -2,10 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 #include "Texture2D.h" +#include <memory> #include <sstream> #include "rkcommon/memory/malloc.h" +#include "rkcommon/tasking/parallel_for.h" #include "stb_image.h" +#include "tinyexr.h" +#include "tiny_dng_loader.h" namespace ospray { namespace sg { @@ -94,8 +98,8 @@ OSPTextureFormat Texture2D::osprayTextureFormat(int components) return OSP_TEXTURE_RGBA32F; } - std::cerr << "#osp:sg: INVALID format " << params.depth << ":" - << components << std::endl; + std::cerr << "#osp:sg: INVALID format " << params.depth << ":" << components + << std::endl; return OSP_TEXTURE_FORMAT_INVALID; } @@ -110,12 +114,10 @@ void Texture2D::loadTexture_OIIO_readFile(std::unique_ptr<ImageInput> &in) const ImageSpec &spec = in->spec(); const auto typeDesc = TypeDescFromC<T>::value(); - std::shared_ptr<void> data(new T[params.size.product() * params.components]); - T *start = (T *)data.get() - + (params.flip ? (params.size.y - 1) * params.size.x * params.components - : 0); - const long int stride = - (params.flip ? -1 : 1) * params.size.x * sizeof(T) * params.components; + std::shared_ptr<T> data(new T[params.size.product() * params.components], + std::default_delete<T[]>()); + T *start = (T *)data.get(); + const long int stride = params.size.x * sizeof(T) * params.components; bool success = in->read_image(typeDesc, start, AutoStride, stride, AutoStride); @@ -165,7 +167,7 @@ void Texture2D::loadTexture_OIIO(const std::string &fileName) void Texture2D::loadTexture_PFM_readFile(FILE *file, float scaleFactor) { size_t size = params.size.product() * params.components; - std::shared_ptr<void> data(new float[size]); + std::shared_ptr<float> data(new float[size], std::default_delete<float[]>()); const size_t dataSize = sizeof(size) * sizeof(float); int rc = fread(data.get(), dataSize, 1, file); @@ -273,13 +275,86 @@ void Texture2D::loadTexture_PFM(const std::string &fileName) } } +// +// EXR (via tinyEXR) +// +void Texture2D::loadTexture_EXR(const std::string &fileName) +{ + // XXX add support for layered EXR? + float *texels; // width * height * RGBA + int width; + int height; + const char *err = nullptr; + + int ret = LoadEXR(&texels, &width, &height, fileName.c_str(), &err); + if (ret != TINYEXR_SUCCESS) { + if (err) { + fprintf(stderr, "ERR : %s\n", err); + std::cerr << "#osp:sg: failed to load EXR texture: " << err << std::endl; + FreeEXRErrorMessage(err); // release memory of error message. + } + } else { + params.size = vec2ul(width, height); + params.components = 4; // always rgba + params.depth = 4; // always float + size_t size = params.size.product() * params.components * params.depth; + + std::shared_ptr<float> data(new float[size], std::default_delete<float[]>()); + std::memcpy(data.get(), texels, size); + + // Move shared_ptr ownership + texelData = data; + + free(texels); // release memory of image data + } +} + +// +// TIFF (via tinyDNG) +// +void Texture2D::loadTexture_TIFF(const std::string &fileName) +{ + std::string warn, err; + std::vector<tinydng::DNGImage> images; + + // Loads all images(IFD) in the DNG file to `images` array. + std::vector<tinydng::FieldInfo> custom_field_lists; + bool ret = tinydng::LoadDNG(fileName.c_str(), custom_field_lists, &images, &warn, &err); + + if (!warn.empty()) { + std::cout << "Warn: " << warn << std::endl; + } + + if (!err.empty()) { + std::cerr << "Err: " << err << std::endl; + } + + if (ret) { + if (images.size() > 1) + std::cerr << "TIFF " << fileName + << " contains multiple images, only loading first one" + << std::endl; + + const tinydng::DNGImage &image = images[0]; + params.size = vec2ul(image.width, image.height); + params.components = image.samples_per_pixel; + params.depth = image.bits_per_sample >> 3; + size_t size = params.size.product() * params.components * params.depth; + + std::shared_ptr<uint8_t> data( + new uint8_t[size], std::default_delete<uint8_t[]>()); + std::memcpy(data.get(), image.data.data(), size); + + // Move shared_ptr ownership + texelData = data; + } +} + // // STBi // void Texture2D::loadTexture_STBi(const std::string &fileName) { - stbi_set_flip_vertically_on_load(params.flip); - const bool isHDR = stbi_is_hdr(fileName.c_str()); const bool is16b = stbi_is_16_bit(fileName.c_str()); @@ -295,9 +370,6 @@ void Texture2D::loadTexture_STBi(const std::string &fileName) texels = (void *)stbi_load( fileName.c_str(), &width, &height, ¶ms.components, 0); - // Set flip on load back to default, STBi maintains a static global. - stbi_set_flip_vertically_on_load(0); - params.size = vec2ul(width, height); params.depth = isHDR ? 4 : is16b ? 2 : 1; @@ -305,7 +377,8 @@ void Texture2D::loadTexture_STBi(const std::string &fileName) // XXX stbi uses malloc/free override these with our alignedMalloc/Free // (and implement a realloc?) to prevent this memcpy? size_t size = params.size.product() * params.components * params.depth; - std::shared_ptr<void> data(new uint8_t[size]); + std::shared_ptr<uint8_t> data( + new uint8_t[size], std::default_delete<uint8_t[]>()); std::memcpy(data.get(), texels, size); texelData = data; stbi_image_free(texels); @@ -332,16 +405,20 @@ bool Texture2D::checkForUDIM(FileName filename) if (hasUDIM()) return true; - // Make sure base file even exists - std::ifstream f(fullName.c_str()); - if (!f.good()) - return false; - // See if base tile "1001" is in the filename. If not, it's not a UDIM. auto found = fullName.rfind("1001"); if (found == std::string::npos) return false; + if (filename.canonical() == "") + std::cerr << "unable to find full path for UDIM file: " << filename + << std::endl; + + // Make sure base file even exists + std::ifstream f(fullName.c_str()); + if (!f.good()) + return false; + // Strip off the "1001" and continue searching for other tiles // by checking existing files of the correct pattern. // This will work for most any consistent *1001* naming scheme. @@ -405,8 +482,9 @@ void Texture2D::loadUDIM_tiles(const FileName &fileName) atlas->params = work->params; atlas->udim_params = work->udim_params; atlas->params.size *= udim_params.dims; - std::shared_ptr<void> data( - new uint8_t[atlas->params.size.product() * texelSize]); + std::shared_ptr<uint8_t> data( + new uint8_t[atlas->params.size.product() * texelSize], + std::default_delete<uint8_t[]>()); atlas->texelData = data; auto atlasStride = atlas->params.size.x * texelSize; @@ -429,9 +507,8 @@ void Texture2D::loadUDIM_tiles(const FileName &fileName) // of the largest size, then scaling all tiles into the atlas. if (work->params.size != tileSize || work->params.depth != tileDepth || work->params.components != tileComponents) { - std::cerr - << "#osp:sg: udim tile size or format doesn't match, skipping: " - << tile.first << std::endl; + std::cerr << "#osp:sg: udim tile size or format doesn't match, skipping: " + << tile.first << std::endl; continue; } @@ -454,6 +531,23 @@ void Texture2D::loadUDIM_tiles(const FileName &fileName) // Texture2D public methods ///////////////////////////////////////////////// +void Texture2D::flipImage() +{ + uint32_t width = params.size.x; + uint32_t height = params.size.y; + int stride = width * params.depth * params.components; + tasking::parallel_for(height >> 1, [&](uint32_t row) { + uint8_t *temp = (uint8_t *)malloc(stride); + uint8_t *src = (uint8_t *)texelData.get() + stride * row; + uint8_t *dst = (uint8_t *)texelData.get() + (height - 1 - row) * stride; + memcpy(temp, dst, stride); + memcpy(dst, src, stride); + memcpy(src, temp, stride); + free(temp); + }); + isFlipped ^= true; +} + bool Texture2D::load(const FileName &_fileName, const bool _preferLinear, const bool _nearestFilter, @@ -489,7 +583,8 @@ bool Texture2D::load(const FileName &_fileName, } else { if (memory) { size_t size = params.size.product() * params.components * params.depth; - std::shared_ptr<void> data(new uint8_t[size]); + std::shared_ptr<uint8_t> data( + new uint8_t[size], std::default_delete<uint8_t[]>()); std::memcpy(data.get(), memory, size); // Move shared_ptr ownership texelData = data; @@ -502,7 +597,11 @@ bool Texture2D::load(const FileName &_fileName, #ifdef USE_OPENIMAGEIO loadTexture_OIIO(fileName); #else - if (_fileName.ext() == "pfm") + if (_fileName.ext() == "exr") + loadTexture_EXR(fileName); + else if (_fileName.ext() == "tif" || _fileName.ext() == "tiff") + loadTexture_TIFF(fileName); + else if (_fileName.ext() == "pfm") loadTexture_PFM(fileName); else loadTexture_STBi(fileName); @@ -517,6 +616,10 @@ bool Texture2D::load(const FileName &_fileName, params.nearestFilter = _nearestFilter; params.colorChannel = _colorChannel; + // If needed, flip the image before creating the data object + if (params.flip && !isFlipped) + flipImage(); + createDataNode(); // If the load was successful, populate children @@ -525,18 +628,28 @@ bool Texture2D::load(const FileName &_fileName, // If not using all channels, set used components to 1 for texture format auto ospTexFormat = - osprayTextureFormat(params.colorChannel < 4 ? 1 : params.components); + osprayTextureFormat(params.colorChannel < 4 ? 1 : params.components); auto texFilter = params.nearestFilter ? OSP_TEXTURE_FILTER_NEAREST - : OSP_TEXTURE_FILTER_BILINEAR; + : OSP_TEXTURE_FILTER_LINEAR; - createChild("format", "int", (int)ospTexFormat); - createChild("filter", "int", (int)texFilter); + createChild("format", "OSPTextureFormat", ospTexFormat); + createChild("filter", "OSPTextureFilter", texFilter); createChild("filename", "filename", fileName).setSGOnly(); - - child("format").setMinMax((int)OSP_TEXTURE_RGBA8, (int)OSP_TEXTURE_R16); + createChild("isFlipped", "bool", params.flip).setSGOnly(); + // Since UDIM is a compiled atlas, user can't just flip image + if (hasUDIM()) + child("isFlipped").setReadOnly(); + + // XXX Running MPI, simply changing the texture data is not enough to + // trigger the flip, therefore do not expose an option for the user + // to change it. Find a lightweight means to signal MPI to update + // texture data to all ranks. (note: The below in preCommit doesn't work) + child("isFlipped").setReadOnly(); + + child("format").setMinMax(OSP_TEXTURE_RGBA8, OSP_TEXTURE_R16); child("filter").setMinMax( - (int)OSP_TEXTURE_FILTER_BILINEAR, (int)OSP_TEXTURE_FILTER_NEAREST); + OSP_TEXTURE_FILTER_LINEAR, OSP_TEXTURE_FILTER_NEAREST); // Add this texture to the cache textureCache[fileName] = this->nodeAs<Texture2D>(); @@ -558,6 +671,28 @@ Texture2D::~Texture2D() void Texture2D::preCommit() { +#if 0 // XXX this does not work for MPI + // If needed, flip the image + if (isFlipped != child("isFlipped").valueAs<bool>()) { + flipImage(); + // Simply changing memory contents will not trigger OSPRay to update texture + // data, especially running MPI offload. Remove and re-add the OSPData node + auto &texture = valueAs<cpp::Texture>(); + texture.commit(); + } +#endif + + std::string guiFilename = child("filename").valueAs<std::string>(); + if (fileName != guiFilename) { + isFlipped = false; + udim_params = {}; + textureCache.erase(fileName); + load(guiFilename, + params.preferLinear, + params.nearestFilter, + params.colorChannel); + } + // make sure to call base-class precommit Texture::preCommit(); } diff --git a/sg/texture/Texture2D.h b/sg/texture/Texture2D.h index 04b55cb8..c13d83b8 100644 --- a/sg/texture/Texture2D.h +++ b/sg/texture/Texture2D.h @@ -37,6 +37,9 @@ struct OSPSG_INTERFACE Texture2D : public Texture const int colorChannel = 4, // default to sampling all channels const void *memory = nullptr); + void flipImage(); + bool isFlipped{false}; + std::string fileName; // UDIM public interface @@ -89,6 +92,8 @@ struct OSPSG_INTERFACE Texture2D : public Texture template <typename T> void loadTexture_OIIO_readFile(std::unique_ptr<OIIO::ImageInput> &in); #else + void loadTexture_EXR(const std::string &fileName); + void loadTexture_TIFF(const std::string &fileName); void loadTexture_PFM(const std::string &fileName); void loadTexture_STBi(const std::string &fileName); void loadTexture_PFM_readFile(FILE *file, float scaleFactor); diff --git a/sg/visitors/GenerateOSPRayMaterials.h b/sg/visitors/GenerateOSPRayMaterials.h index 6b00e03f..c1b224a1 100644 --- a/sg/visitors/GenerateOSPRayMaterials.h +++ b/sg/visitors/GenerateOSPRayMaterials.h @@ -47,7 +47,7 @@ inline bool GenerateOSPRayMaterials::operator()(Node &node, TraversalContext &) if (!mat["handles"].hasChild(rendererType)) { auto &matHandle = mat["handles"].createChild(rendererType, "Node", - cpp::Material(rendererType, mat.osprayMaterialType())); + cpp::Material(mat.osprayMaterialType())); for (auto &c : mat.children()) if (c.second->subType() == "texture_2d" || c.second->subType() == "texture_volume") diff --git a/sg/visitors/RenderScene.h b/sg/visitors/RenderScene.h index 4595aea6..9e6e7b25 100644 --- a/sg/visitors/RenderScene.h +++ b/sg/visitors/RenderScene.h @@ -460,7 +460,7 @@ namespace ospray { std::cout << "number of geometries : " << geomChildren.size() << std::endl; #endif - for (auto geom : geomChildren) { + for (auto &geom : geomChildren) { auto geomHandle = geom->valueAs<cpp::Geometry>().handle(); if (groups.find(geomHandle) != groups.end()) { auto &group = groups[geomHandle]; @@ -471,7 +471,7 @@ namespace ospray { if (node.hasChildOfType(NodeType::VOLUME)) { auto &volChildren = node.childrenOfType(NodeType::VOLUME); - for (auto vol : volChildren) { + for (auto &vol : volChildren) { auto volHandle = vol->valueAs<cpp::Volume>().handle(); if (groups.find(volHandle) != groups.end()) { auto &group = groups[volHandle]; @@ -482,9 +482,9 @@ namespace ospray { if (node.hasChildOfType(NodeType::TRANSFER_FUNCTION)) { auto &tfnChildren = node.childrenOfType(NodeType::TRANSFER_FUNCTION); - for (auto tfn : tfnChildren) { + for (auto &tfn : tfnChildren) { auto volChildren = tfn->childrenOfType(NodeType::VOLUME); - for (auto vol : volChildren) { + for (auto &vol : volChildren) { auto volHandle = vol->valueAs<cpp::Volume>().handle(); if (groups.find(volHandle) != groups.end()) { auto &group = groups[volHandle]; diff --git a/third-party-programs-DPCPP.txt b/third-party-programs-DPCPP.txt new file mode 100644 index 00000000..0e55972e --- /dev/null +++ b/third-party-programs-DPCPP.txt @@ -0,0 +1,110 @@ + +The oneAPI DPC++ Compiler can be found here: + + https://github.com/intel/llvm + +It uses various components with following licenses: + + https://github.com/intel/llvm/blob/master/flang/LICENSE.TXT + https://github.com/intel/llvm/blob/master/compiler-rt/LICENSE.TXT + https://github.com/intel/llvm/blob/master/mlir/LICENSE.TXT + https://github.com/intel/llvm/blob/master/libclc/LICENSE.TXT + https://github.com/intel/llvm/blob/master/libcxxabi/LICENSE.TXT + https://github.com/intel/llvm/blob/master/lld/LICENSE.TXT + https://github.com/intel/llvm/blob/master/cross-project-tests/debuginfo-tests/dexter/LICENSE.txt + https://github.com/intel/llvm/blob/master/libc/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang-tools-extra/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang-tools-extra/clang-tidy/cert/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT + https://github.com/intel/llvm/blob/master/lldb/LICENSE.TXT + https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE + https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/six/LICENSE + https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/pexpect-4.6/LICENSE + https://github.com/intel/llvm/blob/master/polly/LICENSE.TXT + https://github.com/intel/llvm/blob/master/polly/lib/External/isl/LICENSE + https://github.com/intel/llvm/blob/master/polly/lib/External/isl/imath/LICENSE + https://github.com/intel/llvm/blob/master/polly/tools/GPURuntime/LICENSE.TXT + https://github.com/intel/llvm/blob/master/sycl/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm-spirv/LICENSE.TXT + https://github.com/intel/llvm/blob/master/bolt/LICENSE.TXT + https://github.com/intel/llvm/blob/master/pstl/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/utils/lit/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/utils/unittest/googletest/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/utils/unittest/googlemock/LICENSE.txt + https://github.com/intel/llvm/blob/master/llvm/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/include/llvm/Support/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/lib/Support/BLAKE3/LICENSE + https://github.com/intel/llvm/blob/master/llvm/test/YAMLParser/LICENSE.txt + https://github.com/intel/llvm/blob/master/libunwind/LICENSE.TXT + https://github.com/intel/llvm/blob/master/openmp/LICENSE.TXT + https://github.com/intel/llvm/blob/master/openmp/runtime/src/thirdparty/ittnotify/LICENSE.txt + https://github.com/intel/llvm/blob/master/third-party/benchmark/LICENSE + https://github.com/intel/llvm/blob/master/libcxx/LICENSE.TXT + +The following people and companies contributed to the LLVM project: + + https://github.com/intel/llvm/blob/master/compiler-rt/CREDITS.TXT + https://github.com/intel/llvm/blob/master/libclc/CREDITS.TXT + https://github.com/intel/llvm/blob/master/libcxxabi/CREDITS.TXT + https://github.com/intel/llvm/blob/master/polly/CREDITS.txt + https://github.com/intel/llvm/blob/master/pstl/CREDITS.txt + https://github.com/intel/llvm/blob/master/llvm/CREDITS.TXT + https://github.com/intel/llvm/blob/master/openmp/CREDITS.txt + https://github.com/intel/llvm/blob/master/libcxx/CREDITS.TXT + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2020 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/third-party-programs-Embree.txt b/third-party-programs-Embree.txt new file mode 100644 index 00000000..a2a0ff45 --- /dev/null +++ b/third-party-programs-Embree.txt @@ -0,0 +1,1821 @@ +Intel(R) Embree Third Party Programs File + +This file contains the list of third party software (third party +programs) contained in the Intel software and their required notices +and/or license terms. This third party software, even if included with +the distribution of the Intel software, may be governed by separate +license terms, including without limitation, third party license +terms, other Intel software license terms, and open source software +license terms. These separate license terms govern your use of the +third party programs as set forth in the third-party-programs.txt or +other similarly-named text file. + +Third party programs and their corresponding required notices and/or +license terms are listed below. + + +1. Apache License 2.0 +------------------------------------------------------------- + +1.1. Intel(R) oneAPI Threading Building Blocks (TBB) + https://github.com/oneapi-src/oneTBB + Copyright Intel + +1.2. Intel(R) Open Image Denoise (OIDN) + https://github.com/OpenImageDenoise/oidn + Copyright Intel + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +2. Apache License 2.0 with LLVM Exceptions +------------------------------------------------------------- + +2.1. oneAPI DPC++ Compiler + https://github.com/intel/llvm/ + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + + +3. Pixar Modified Apache License 2.0 +------------------------------------------------------------- + +3.1 OpenSubdiv + https://github.com/PixarAnimationStudios/OpenSubdiv + Copyright 2013 Pixar + All rights reserved. + + This product includes software developed at: + Pixar (http://www.pixar.com/). + Dreamworks Animation (http://www.dreamworksanimation.com/) + Autodesk, Inc. (http://www.autodesk.com/). + Google, Inc. (http://www.google.com/). + DigitalFish (http://digitalfish.com/). + + + + This product includes software developed at: + Pixar (http://www.pixar.com/). + + + Modified Apache 2.0 License + + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor + and its affiliates, except as required to comply with Section 4(c) of + the License and to reproduce the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + +4. zLib License +------------------------------------------------------------- + +4.1. GLFW + https://github.com/glfw/glfw + Copyright (c) 2002-2006 Marcus Geelnard + Copyright (c) 2006-2019 Camilla Loewy + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +Altered source versions must be plainly marked as such, and must not +be misrepresented as being the original software. + +This notice may not be removed or altered from any source +distribution. + +You can find this license in the file LICENSE.md of the GLFW source +tree and in the comment header of each source file. + + +5. MIT License +------------------------------------------------------------- + +5.1. Gruenschloss Halton + https://gruenschloss.org/halton/halton.zip + Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) + +5.2. ImGui + https://github.com/ocornut/imgui + Copyright (c) 2014-2020 Omar Cornut + +5.3. PCG Random Number Generation, C++ Edition + https://github.com/imneme/pcg-cpp + Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors + +5.4. SSE2NEON + https://github.com/DLTcollab/sse2neon + +5.5. stb single-file libraries for C/C++ + https://github.com/nothings/stb + Copyright (c) 2017 Sean Barrett + +5.6. A GPU Optimizer for Blue-Noise Screen-Space Sampler + https://github.com/unity-grenoble/sampling_bluenoise_sig21 + Copyright (c) 2020 Sylvain Durand + + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +6. BSD 3-clause License +------------------------------------------------------------- + +6.1. OpenEXR + https://github.com/AcademySoftwareFoundation/openexr + +Copyright (c) Contributors to the OpenEXR Project. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +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. + + +7. BSD 3-clause License + Dependencies +------------------------------------------------------------- + +7.1. TinyEXR + https://github.com/syoyo/tinyexr + +Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the Syoyo Fujita nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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. + +TinyEXR contains some OpenEXR code, which is licensed under: + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +8. Customized BSD 3-clause License +------------------------------------------------------------- + +8.1. Syrah + https://github.com/boulos/syrah + Copyright (c) 2009, Stanford University, and authors listed below. + All rights reserved. + +Original authors: + Solomon Boulos + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Stanford University nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +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. + + +9. Boost Software License - Version 1.0 +------------------------------------------------------------- + +9.1. Catch2 + https://github.com/catchorg/Catch2 + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +10. Visual C++ Redistributables for Visual Studio +------------------------------------------------------------- + +1. License. This software package from Intel (the “Software Packageâ€) contains code from Microsoft (the “Distributable Codeâ€). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use and redistribute the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code on a stand-alone basis. +2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: +• work around any technical limitations in the Distributable Code; +• reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; +• remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; +• use the Distributable Code in any way that is against the law; or +• share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. +3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS†WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. +4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. +This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. +5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. + + +11. Pixar Modified Apache 2.0 +------------------------------------------------------------- + +11.1 Universal Scene Description + https://github.com/PixarAnimationStudios/USD + Copyright 2016 Pixar + All rights reserved. + +Modified Apache 2.0 License + + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor + and its affiliates, except as required to comply with Section 4(c) of + the License and to reproduce the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +============================================================ +RapidJSON +============================================================ + +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS AND 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. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +============================================================ +pygilstate_check +============================================================ + +The MIT License (MIT) + +Copyright (c) 2014, Pankaj Pandey + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +============================================================ +double-conversion +============================================================ + +Copyright 2006-2011, the V8 project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +============================================================ +OpenEXR/IlmBase/Half +============================================================ + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +============================================================ +Apple Technical Q&A QA1361 - Detecting the Debugger +https://developer.apple.com/library/content/qa/qa1361/_index.html +============================================================ + +Sample code project: Detecting the Debugger +Version: 1.0 + +Abstract: Shows how to determine if code is being run under the debugger. + +IMPORTANT: This Apple software is supplied to you by Apple +Inc. ("Apple") in consideration of your agreement to the following +terms, and your use, installation, modification or redistribution of +this Apple software constitutes acceptance of these terms. If you do +not agree with these terms, please do not use, install, modify or +redistribute this Apple software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, Apple grants you a personal, non-exclusive +license, under Apple's copyrights in this original Apple software (the +"Apple Software"), to use, reproduce, modify and redistribute the Apple +Software, with or without modifications, in source and/or binary forms; +provided that if you redistribute the Apple Software in its entirety and +without modifications, you must retain this notice and the following +text and disclaimers in all such redistributions of the Apple Software. +Neither the name, trademarks, service marks or logos of Apple Inc. may +be used to endorse or promote products derived from the Apple Software +without specific prior written permission from Apple. Except as +expressly stated in this notice, no other rights or licenses, express or +implied, are granted by Apple herein, including but not limited to any +patent rights that may be infringed by your derivative works or by other +works in which the Apple Software may be incorporated. + +The Apple Software is provided by Apple on an "AS IS" basis. APPLE +MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION +THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND +OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + +IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, +MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED +AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), +STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +============================================================ +LZ4 +============================================================ + +LZ4 - Fast LZ compression algorithm +Copyright (C) 2011-present, Yann Collet. + +BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +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. + +You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 + +============================================================ +stb +============================================================ + +stb_image - v2.19 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + +stb_image_resize - v0.95 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + +stb_image_write - v1.09 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +============================================================ +pugixml +============================================================ + +MIT License + +Copyright (c) 2006-2019 Arseny Kapoulkine + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +============================================================ +Vulkan C++ examples and demos (dome light texture filtering) +============================================================ + +The MIT License (MIT) + +Copyright (c) 2016 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +============================================================ +pbrt (Hammersley Low-Discrepancy Sampling Sequence) +============================================================ + +Copyright (c) 1998-2015, Matt Pharr, Greg Humphreys, and Wenzel Jakob. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +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. + + +============================================================ +Draco +============================================================ +USD bundles Draco, which is available under the Apache 2.0 license. For details, +see https://github.com/google/draco/blob/master/README.md. + + +============================================================ +Roboto Fonts +============================================================ +USD bundles Roboto fonts, which is available under the Apache 2.0 license. +For details, see https://fonts.google.com/specimen/Roboto#license + + +============================================================ +Roboto Mono Fonts +============================================================ +USD bundles Roboto Mono fonts, which is available under the Apache 2.0 license. +For details, see https://fonts.google.com/specimen/Roboto+Mono#license + + +============================================================ +Vulkan Memory Allocator +============================================================ +Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +============================================================ +Spirv Reflect +============================================================ +Copyright 2017-2018 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +============================================================ +khrplatform.h +============================================================ +Copyright (c) 2008-2018 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + + +============================================================ +surfgrad-bump-standalone-demo +============================================================ +MIT License + +Copyright (c) 2020 mmikk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +================================================================ +Tessil robin-map +================================================================ +MIT License + +Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +11. Intel End User License Agreement for Developer Tools (Version October 2021) +------------------------------------------------------------------------------- + +11.1 Intel(R) oneAPI DPC++/C++ Compiler + + +Intel End User License Agreement for Developer Tools (Version October 2021) + + + +IMPORTANT NOTICE - PLEASE READ AND AGREE BEFORE DOWNLOADING, INSTALLING, COPYING OR USING + +This Agreement is between you, or the company or other legal entity that you represent and warrant you have the legal authority to bind, (each, "You" or "Your") and Intel Corporation and its subsidiaries (collectively, "Intel") regarding Your use of the Materials. By downloading, installing, copying or using the Materials, You agree to be bound by the terms of this Agreement. If You do not agree to the terms of this Agreement, or do not have legal authority or required age to agree to them, do not download, install, copy or use the Materials. + + + +LICENSE DEFINITIONS. + + + +A. "Cloud Provider" means a third party service provider offering a cloud-based platform, infrastructure, application or storage services, such as Microsoft Azure or Amazon Web Services, which You may only utilize to host the Materials subject to the restrictions set forth in Section 2.3 B. + + + +B. "Derivative Work" means a derivative work, as defined in 17 U.S.C. § 101, of the Source Code. + + + +C. "Executable Code" means computer programming code in binary form suitable for machine execution by a processor without the intervening steps of interpretation or compilation. + + + +D. "Materials" mean the software, documentation, the software product serial number, and other collateral, including any updates, made available to You by Intel under this Agreement. Materials include Redistributables, Executable Code, Source Code, Sample Source Code, and Pre-Release Materials, but do not include Third Party Software. + + + +E. "Pre-Release Materials" mean the Materials, or portions of the Materials, that are identified (in the product release notes, on Intel's download website for the Materials or elsewhere) or labeled as pre-release, prototype, alpha or beta code and, as such, are deemed to be pre-release code (i) which may not be fully functional or tested and may contain bugs or errors; (ii) which Intel may substantially modify in its development of a production version; or (iii) for which Intel makes no assurances that it will ever develop or make a production version generally available. Pre-Release Materials are subject to the terms of Section 3.2. + + + +F. "Reciprocal Open Source Software" means any software that is subject to a license which requires that (i) it must be distributed in source code form; (ii) it must be licensed under the same open source license terms; and (iii) its derivative works must be licensed under the same open source license terms. Examples of this type of license are the GNU General Public License or the Mozilla Public License. + + + +G. "Redistributables" mean the files (if any) listed in the "redist.txt," "redist-rt.txt" or similarlynamed text files that may be included in the Materials. Redistributables include Sample Source Code. + + + +H. "Sample Source Code" means those portions of the Materials that are Source Code and are identified as sample code. Sample Source Code may not have been tested or validated by Intel and is provided purely as a programming example. + + + +I. "Source Code" means the software portion of the Materials provided in human readable format. + + + +J. "Third Party Software" mean the files (if any) listed in the "third-party-software.txt" or other similarly-named text file that may be included in the Materials for the applicable software. +Third Party Software is subject to the terms of Section 2.2. + + + +K. "Your Product" means one or more applications, products or projects developed by or for You using the Materials. + + + +2. LICENSE GRANTS. + + + +2.1 License to the Materials. Subject to the terms and conditions of this Agreement, Intel grants You a non-exclusive, worldwide, non-assignable, non-sublicensable, limited right and license under its copyrights, to: + + + +A. reproduce internally a reasonable number of copies of the Materials for Your personal or business use; + + + +B. use the Materials solely for Your personal or business use to develop Your Product, in accordance with the documentation included as part of the Materials; + + + +C. modify or create Derivative Works only of the Redistributables, or any portions, that are provided to You in Source Code; + + + +D. distribute (directly and through Your distributors, resellers, and other channel partners, if applicable), the Redistributables, including any modifications to or Derivative Works of the Redistributables or any portions made pursuant to Section 2.1.C subject to the following conditions: + + + +(1) Any distribution of the Redistributables must only be as part of Your Product which must add significant primary functionality different than that of the Redistributables themselves; + + + +(2) You must only distribute the Redistributables originally provided to You by Intel only in Executable Code subject to a license agreement that prohibits reverse engineering, decompiling or disassembling the Redistributables; + + + +(3) This distribution right includes a limited right to sublicense only the Intel copyrights in the Redistributables and only to the extent necessary to perform, display, and distribute the Redistributables (including Your modifications and Derivative Works of the Redistributables provided in Source Code) solely as incorporated in Your Product; and + + + +(4) You: (i) will be solely responsible to Your customers for any update, support obligation or other obligation or liability which may arise from the distribution of Your Product, (ii) will not make any statement that Your Product is "certified" or that its performance is guaranteed by Intel or its suppliers, (iii) will not use Intel's or its suppliers' names or trademarks to market Your Product, (iv) will comply with any additional restrictions which are included in the text files with the Redistributables and in Section 3 below, (v) will indemnify, hold harmless, and defend Intel and its suppliers from and against any claims or lawsuits, costs, damages, and expenses, including attorney's fees, that arise or result from (a) Your modifications or Derivative Works of the Materials or (b) Your distribution of Your Product. + + + +2.2 Third Party Software. Third Party Software, even if included with the distribution of the Materials, may be governed by separate license terms, including without limitation, third party license terms, open source software notices and terms, and/or other Intel software license terms. These separate license terms solely govern Your use of the Third Party Software. + + + +2.3 Third Party Use. + +A. If You are an entity, Your contractors may use the Materials under the license specified in Section 2, provided: (i) their use of the Materials is solely on behalf of and in support of Your business, (ii) they agree to the terms and conditions of this Agreement, and (iii) You are solely responsible for their use, misuse or disclosure of the Materials. + + + +B. You may utilize a Cloud Provider to host the Materials for You, provided: (i) the Cloud Provider may only host the Materials for Your exclusive use and may not use the Materials for any other purpose whatsoever, including the restriction set forth in Section 3.1(xi); (ii) the Cloud Provider's use of the Materials must be solely on behalf of and in support of Your Product, and (iii) You will indemnify, hold harmless, and defend Intel and its suppliers from and against any claims or lawsuits, costs, damages, and expenses, including attorney's fees, that arise or result from Your Cloud Provider's use, misuse or disclosure of the Materials. + + + +3. LICENSE CONDITIONS. + + + +3.1 Restrictions. Except as expressly provided in this Agreement, You may NOT: (i) use, reproduce, disclose, distribute, or publicly display the Materials; (ii) share, publish, rent or lease the Materials to any third party; (iii) assign this Agreement or transfer the Materials; (iv) modify, adapt, or translate the Materials in whole or in part; (v) reverse engineer, decompile, or disassemble the Materials, or otherwise attempt to derive the source code for the software; (vi) work around any technical limitations in the Materials; (vii) distribute, sublicense or transfer any Source Code, modifications or Derivative Works of any Source Code to any third party; (viii) remove, minimize, block or modify any notices of Intel or its suppliers in the Materials; (ix) include the Redistributables in malicious, deceptive, or unlawful programs or products or use the Materials in any way that is against the law; (x) modify, create a Derivative Work, link, or distribute the Materials so that any part of it becomes Reciprocal Open Source Software; (xi) use the Materials directly or indirectly for SaaS services or service bureau purposes (i.e., a service that allows use of or access to the Materials by a third party as part of that service, such as the salesforce.com service business model). + + + +3.2 Pre-Release Materials. If You receive Pre-Release Materials, You may reproduce a reasonable number of copies and use the Pre-Release Materials for evaluation and testing purposes only. You may not (i) modify or incorporate the Pre-Release Materials into Your Product; (ii) continue to use the Pre-Release Materials once a commercial version is released; or (iii) disclose to any third party any benchmarks, performance results, or other information relating to the Pre-Release Materials. Intel may waive these restrictions in writing at its sole discretion; however, if You decide to use the Pre-Release Materials in Your Product (even with Intel's waiver), You acknowledge and agree that You are fully responsible for any and all issues that result from such use. + + + +3.3 Safety-Critical, and Life-Saving Applications; Indemnity. The Materials may provide information relevant to safety-critical applications ("Safety-Critical Applications") to allow compliance with functional safety standards or requirements. You acknowledge and agree that safety is Your responsibility. To the extent You use the Materials to create, or as part of, products used in Safety-Critical Applications, it is Your responsibility to design, manage, and ensure that there are system-level safeguards to anticipate, monitor, and control system failures, and You agree that You are solely responsible for all applicable regulatory standards and safety-related requirements concerning Your use of the Materials in Safety Critical Applications. + + + +Should You use the Materials for Safety-Critical Applications or in any type of a system or application in which the failure of the Materials could create a situation where personal injury or death may occur (e.g., medical systems, life-sustaining or life-saving systems) ("Life-Saving Applications"), You agree to indemnify, defend, and hold Intel and its representatives harmless against any claims or lawsuits, costs, damages, and expenses, including reasonable attorney fees, arising in any way out of Your use of the Materials in Safety-Critical Applications or Life-Saving Applications and claims of product liability, personal injury or death associated with those applications; even if such claims allege that Intel was negligent or strictly liable regarding the design or manufacture of the Materials or its failure to warn regarding the Materials. + + + +3.4 Media Format Codecs and Digital Rights Management. You acknowledge and agree that Your use of the Materials or distribution of the Redistributables with Your Product as permitted by this Agreement may require You to procure license(s) from third parties that may hold intellectual property rights applicable to any media decoding, encoding or transcoding technology (e.g., the use of an audio or video codec) and/or digital rights management capabilities of the Materials, if any. Should any such additional licenses be required, You are solely responsible for obtaining any such licenses and agree to obtain any such licenses at Your own expense. + + + +4. DATA COLLECTION AND PRIVACY. + + + +4.1 Data Collection. The Materials may generate and collect anonymous data and/or provisioning data about the Materials and/or the development environment and transmit the data to Intel as a one-time event during installation. Optional data may also be collected by the Materials, however, You will be provided notice of the request to collect optional data and no optional data will be collected without Your consent. All data collection by Intel is performed pursuant to relevant privacy laws, including notice and consent requirements. + + + +4.2 Intel's Privacy Notice. Intel is committed to respecting Your privacy. To learn more about Intel's privacy practices, please visit http://www.intel.com/privacy. + + + +5. OWNERSHIP. Title to the Materials and all copies remain with Intel or its suppliers. The Materials are protected by intellectual property rights, including without limitation, United States copyright laws and international treaty provisions. You will not remove any copyright or other proprietary notices from the Materials. Except as expressly provided herein, no license or right is granted to You directly or by implication, inducement, estoppel or otherwise; specifically, Intel does not grant any express or implied right to You under Intel patents, copyrights, trademarks, or trade secrets. + + + +6. NO WARRANTY AND NO SUPPORT. + + + +6.1 No Warranty. Disclaimer. Intel disclaims all warranties of any kind and the terms and remedies provided in this Agreement are instead of any other warranty or condition, express, implied or statutory, including those regarding merchantability, fitness for any particular purpose, non-infringement or any warranty arising out of any course of dealing, usage of trade, proposal, specification or sample. Intel does not assume (and does not authorize any person to assume on its behalf) any liability. + + + +6.2 No Support; Priority Support. Intel may make changes to the Materials, or to items referenced therein, at any time without notice, but is not obligated to support, update or provide training for the Materials under the terms of this Agreement. Intel offers free community and paid priority support options. More information on these support options can be found at: + +https://software.intel.com/content/www/us/en/develop/support/priority-support.html. + + + +7. LIMITATION OF LIABILITY. + + + +7.1 Intel will not be liable for any of the following losses or damages (whether such losses or damages were foreseen, foreseeable, known or otherwise): (i) loss of revenue; (ii) loss of actual or anticipated profits; (iii) loss of the use of money; (iv) loss of anticipated savings; (v) loss of business; (vi) loss of opportunity; (vii) loss of goodwill; (viii) loss of use of the Materials; (ix) loss of reputation; (x) loss of, damage to, or corruption of data; or (xi) any indirect, incidental, special or consequential loss of damage however caused (including loss or damage of the type specified in this Section 7). + + + +7.2 Intel's total cumulative liability to You, including for direct damages for claims relating to this Agreement, and whether for breach of contract, negligence, or for any other reason, will not exceed $100. + + + +7.3 You acknowledge that the limitations of liability provided in this Section 7 are an essential part of this Agreement. You agree that the limitations of liability provided in this Agreement with respect to Intel will be conveyed to and made binding upon any customer of Yours that acquires the Redistributables. + + + +8. USER SUBMISSIONS. Should you provide Intel with comments, modifications, corrections, enhancements or other input ("Feedback") related to the Materials, Intel will be free to use, disclose, reproduce, license or otherwise distribute or exploit the Feedback in its sole discretion without any obligations or restrictions of any kind, including without limitation, intellectual property rights or licensing obligations. If You wish to provide Intel with information that You intend to be treated as confidential information, Intel requires that such confidential information be provided pursuant to a non-disclosure agreement ("NDA"); please contact Your Intel representative to ensure the proper NDA is in place. + + + +9. NON-DISCLOSURE. Information provided by Intel to You may include information marked as confidential. You must treat such information as confidential under the terms of the applicable NDA between Intel and You. If You have not entered into an NDA with Intel, You must not disclose, distribute or make use of any information marked as confidential, except as expressly authorized in writing by Intel. Intel retains all rights in and to its confidential information specifications, designs, engineering details, discoveries, inventions, patents, copyrights, trademarks, trade secrets, and other proprietary rights relating to the Materials. Any breach by You of the confidentiality obligations provided for in this Section 9 will cause irreparable injury to Intel for which money damages may be inadequate to compensate Intel for losses arising from such a breach. Intel may obtain equitable relief, including injunctive relief, if You breach or threaten to breach Your confidentiality obligations. + + + +10. TERM AND TERMINATION. This Agreement becomes effective on the date You accept this Agreement and will continue until terminated as provided for in this Agreement. The term for any Pre-Release Materials terminates upon release of a commercial version. This Agreement will terminate if You are in breach of any of its terms and conditions. Upon termination, You will promptly destroy the Materials and all copies. In the event of termination of this Agreement, Your license to any Redistributables distributed by You in accordance with the terms and conditions of this Agreement, prior to the effective date of such termination, will survive any such termination of this Agreement. Sections 1, 2.1.D(4)(v), 2.2, 2.3.A(iii), 2.3.B(iii), 3.3, 5, 6, 7, 8, 9, 10 (with respect to these survival provisions in the last sentence), and 12 will survive expiration or termination of this Agreement. + + + +11. U.S. GOVERNMENT RESTRICTED RIGHTS. The technical data and computer software covered by this license is a "Commercial Item," as such term is defined by the FAR 2.101 (48 C.F.R. 2.101) and is "commercial computer software" and "commercial computer software documentation" as specified under FAR 12.212 (48 C.F.R. 12.212) or DFARS 227.7202 (48 C.F.R. 227.7202), as applicable. This commercial computer software and related documentation is provided to end users for use by and on behalf of the U.S. Government with only those rights as are granted to all other end users pursuant to the terms and conditions of this Agreement. + + + +12. GENERAL PROVISIONS. + + + +12.1 ENTIRE AGREEMENT. This Agreement contains the complete and exclusive agreement and understanding between the parties concerning the subject matter of this Agreement, and supersedes all prior and contemporaneous proposals, agreements, understanding, negotiations, representations, warranties, conditions, and communications, oral or written, between the parties relating to the same subject matter. Each party acknowledges and agrees that in entering into this Agreement it has not relied on, and will not be entitled to rely on, any oral or written representations, warranties, conditions, understanding, or communications between the parties that are not expressly set forth in this Agreement. The express provisions of this Agreement control over any course of performance, course of dealing, or usage of the trade inconsistent with any of the provisions of this Agreement. The provisions of this Agreement will prevail notwithstanding any different, conflicting, or additional provisions that may appear on any purchase order, acknowledgement, invoice, or other writing issued by either party in connection with this Agreement. No modification or amendment to this Agreement will be effective unless in writing and signed by authorized representatives of each party, and must specifically identify this Agreement by its title and version (e.g., "Intel End User License Agreement for Developer Tools (Version October 2021)"); except that Intel may make changes to this Agreement as it distributes new versions of the Materials. When changes are made, Intel will make a new version of the Agreement available on its website. If You received a copy of this Agreement translated into another language, the English language version of this Agreement will prevail in the event of any conflict between versions. + + + +12.2 EXPORT. You acknowledge that the Materials and all related technical information are subject to export controls and you agree to comply with all laws and regulations of the United States and other applicable governments governing export, re-export, import, transfer, distribution, and use of the Materials. In particular, but without limitation, the Materials may not be exported or re-exported (i) into any U.S. embargoed countries or (ii) to any person or entity listed on a denial order published by the U.S. government or any other applicable governments. By using the Materials, You represent and warrant that You are not located in any such country or on any such list. You also agree that You will not use the Materials for, or sell or transfer them to a third party who is known or suspected to be involved in, any purposes prohibited by the U.S. government or other applicable governments, including, without limitation, the development, design, manufacture, or production of nuclear, missile, chemical or biological weapons. + + + +12.3 GOVERNING LAW, JURISDICTION, AND VENUE. All disputes arising out of or related to this Agreement, whether based on contract, tort, or any other legal or equitable theory, will in all respects be governed by, and construed and interpreted under, the laws of the United States of America and the State of Delaware, without reference to conflict of laws principles. The parties agree that the United Nations Convention on Contracts for the International Sale of Goods (1980) is specifically excluded from and will not apply to this Agreement. All disputes arising out of or related to this Agreement, whether based on contract, tort, or any other legal or equitable theory, will be subject to the exclusive jurisdiction of the courts of the State of Delaware or of the Federal courts sitting in that State. Each party submits to the personal jurisdiction of those courts and waives all objections to that jurisdiction and venue for those disputes. + + + +12.4 SEVERABILITY. The parties intend that if a court holds that any provision or part of this Agreement is invalid or unenforceable under applicable law, the court will modify the provision to the minimum extent necessary to make it valid and enforceable, or if it cannot be made valid and enforceable, the parties intend that the court will sever and delete the provision or part from this Agreement. Any change to or deletion of a provision or part of this Agreement under this Section will not affect the validity or enforceability of the remainder of this Agreement, which will continue in full force and effect. + + + +12. Additional Third Party Program Files +------------------------------------------------------------- + +The following third party programs have their own third party program +files. These additional third party program files are as follows: + +12.1. Intel(R) oneAPI Threading Building Blocks (TBB) + third-party-programs-oneTBB.txt + +12.2. Intel(R) Open Image Denoise (OIDN) + third-party-programs-OIDN.txt file. + +12.3. oneAPI DPC++ Compiler + third-party-programs-DPCPP.txt file. + +12.4. Intel(R) oneAPI DPC++/C++ Compiler + third-party-programs-oneAPI-DPCPP.txt file. + diff --git a/third-party-programs-ISPC.txt b/third-party-programs-ISPC.txt new file mode 100644 index 00000000..0925f43a --- /dev/null +++ b/third-party-programs-ISPC.txt @@ -0,0 +1,2109 @@ +Intel(R) Implicit SPMD Program Compiler (Intel(R) ISPC) Third Party Programs +File. + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license +terms. This third party software, even if included with the distribution of the +Intel software, may be governed by separate license terms, including without +limitation, third party license terms, other Intel software license terms, and +open source software license terms. These separate license terms govern your use +of the third party programs as set forth in the “third-party-programs.txt†or +other similarly named text file. + +Third party programs and their corresponding required notices and/or license +terms are listed below. + +-------------------------------------------------------------------------------- + +1. LLVM Project. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +2. Syrah library. + +Copyright (c) 2009, Stanford University, and authors listed below. +All rights reserved. + +Original authors: + Solomon Boulos + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Stanford University nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +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. + +-------------------------------------------------------------------------------- + +3. IEEE 754r Half Precision Floating Point Converter. + (c) 2009 by James Tursa, All Rights Reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +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. + +-------------------------------------------------------------------------------- + +4. libncurses + + libtinfo + + +Copyright 2018-2021,2022 Thomas E. Dickey +Copyright 1998-2017,2018 Free Software Foundation, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, distribute with modifications, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name(s) of the above copyright +holders shall not be used in advertising or otherwise to promote the +sale, use or other dealings in this Software without prior written +authorization. + +-------------------------------------------------------------------------------- + +5. GNU libstdc++ + + libgcc + +GCC is Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, +1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 +Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Files that have exception clauses are licensed under the terms of the +GNU General Public License; either version 3, or (at your option) any +later version. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License is in `/usr/share/common-licenses/GPL', version 3 of this +license in `/usr/share/common-licenses/GPL-3'. + +The following runtime libraries are licensed under the terms of the +GNU General Public License (v3 or later) with version 3.1 of the GCC +Runtime Library Exception (included in this file): + + - libgcc (libgcc/, gcc/libgcc2.[ch], gcc/unwind*, gcc/gthr*, + gcc/coretypes.h, gcc/crtstuff.c, gcc/defaults.h, gcc/dwarf2.h, + gcc/emults.c, gcc/gbl-ctors.h, gcc/gcov-io.h, gcc/libgcov.c, + gcc/tsystem.h, gcc/typeclass.h). + - libatomic + - libdecnumber + - libgomp + - libitm + - libssp + - libstdc++-v3 + - libobjc + - libgfortran + - The libgnat-9 Ada support library and libgnatvsn library. + - Various config files in gcc/config/ used in runtime libraries. + - libvtv + +The libbacktrace library is licensed under the following terms: + +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. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + + +The libsanitizer libraries (libasan, liblsan, libtsan, libubsan) are +licensed under the following terms: + +Copyright (c) 2009-2014 by the LLVM contributors. + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +The libffi library is licensed under the following terms: + + libffi - Copyright (c) 1996-2003 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + +The documentation is licensed under the GNU Free Documentation License (v1.2). +On Debian GNU/Linux systems, the complete text of this license is in +`/usr/share/common-licenses/GFDL-1.2'. + + +GCC RUNTIME LIBRARY EXCEPTION + +Version 3.1, 31 March 2009 + +Copyright (C) 2009 Free Software Foundation, Inc. <http://fsf.org/> + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +This GCC Runtime Library Exception ("Exception") is an additional +permission under section 7 of the GNU General Public License, version +3 ("GPLv3"). It applies to a given file (the "Runtime Library") that +bears a notice placed by the copyright holder of the file stating that +the file is governed by GPLv3 along with this Exception. + +When you use GCC to compile a program, GCC may combine portions of +certain GCC header files and runtime libraries with the compiled +program. The purpose of this Exception is to allow compilation of +non-GPL (including proprietary) programs to use, in this way, the +header files and runtime libraries covered by this Exception. + +0. Definitions. + +A file is an "Independent Module" if it either requires the Runtime +Library for execution after a Compilation Process, or makes use of an +interface provided by the Runtime Library, but is not otherwise based +on the Runtime Library. + +"GCC" means a version of the GNU Compiler Collection, with or without +modifications, governed by version 3 (or a specified later version) of +the GNU General Public License (GPL) with the option of using any +subsequent versions published by the FSF. + +"GPL-compatible Software" is software whose conditions of propagation, +modification and use would permit combination with GCC in accord with +the license of GCC. + +"Target Code" refers to output from any compiler for a real or virtual +target processor architecture, in executable form or suitable for +input to an assembler, loader, linker and/or execution +phase. Notwithstanding that, Target Code does not include data in any +format that is used as a compiler intermediate representation, or used +for producing a compiler intermediate representation. + +The "Compilation Process" transforms code entirely represented in +non-intermediate languages designed for human-written code, and/or in +Java Virtual Machine byte code, into Target Code. Thus, for example, +use of source code generators and preprocessors need not be considered +part of the Compilation Process, since the Compilation Process can be +understood as starting with the output of the generators or +preprocessors. + +A Compilation Process is "Eligible" if it is done using GCC, alone or +with other GPL-compatible software, or if it is done without using any +work based on GCC. For example, using non-GPL-compatible Software to +optimize any GCC intermediate representations would not qualify as an +Eligible Compilation Process. + +1. Grant of Additional Permission. + +You have permission to propagate a work of Target Code formed by +combining the Runtime Library with Independent Modules, even if such +propagation would otherwise violate the terms of GPLv3, provided that +all Target Code was generated by Eligible Compilation Processes. You +may then convey such a combination under terms of your choice, +consistent with the licensing of the Independent Modules. + +2. No Weakening of GCC Copyleft. + +The availability of this Exception does not imply any general +presumption that third-party software is unaffected by the copyleft +requirements of the license of GCC. + + +libquadmath/*.[hc]: + + Copyright (C) 2010 Free Software Foundation, Inc. + Written by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + Written by Tobias Burnus <burnus@net-b.de> + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +libquadmath/math: + +atanq.c, expm1q.c, j0q.c, j1q.c, log1pq.c, logq.c: + Copyright 2001 by Stephen L. Moshier <moshier@na-net.ornl.gov> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + +coshq.c, erfq.c, jnq.c, lgammaq.c, powq.c, roundq.c: + Changes for 128-bit __float128 are + Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov> + and are incorporated herein by permission of the author. The author + reserves the right to distribute this material elsewhere under different + copying permissions. These modifications are distributed here under + the following terms: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + +ldexpq.c: + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + +cosq_kernel.c, expq.c, sincos_table.c, sincosq.c, sincosq_kernel.c, +sinq_kernel.c, truncq.c: + Copyright (C) 1997, 1999 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + +isinfq.c: + * Written by J.T. Conklin <jtc@netbsd.org>. + * Change for long double by Jakub Jelinek <jj@ultra.linux.cz> + * Public domain. + +llroundq.c, lroundq.c, tgammaq.c: + Copyright (C) 1997, 1999, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and + Jakub Jelinek <jj@ultra.linux.cz>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + +log10q.c: + Cephes Math Library Release 2.2: January, 1991 + Copyright 1984, 1991 by Stephen L. Moshier + Adapted for glibc November, 2001 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + +remaining files: + + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + + +gcc/go/gofrontend, libgo: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +D: +gdc-9 GNU D Compiler +libphobos-9-dev D standard runtime library + +The D source package is made up of the following components. + +The D front-end for GCC: + - d/* + +Copyright (C) 2004-2007 David Friedman +Modified by Vincenzo Ampolo, Michael Parrot, Iain Buclaw, (C) 2009, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License is in `/usr/share/common-licenses/GPL', version 2 of this +license in `/usr/share/common-licenses/GPL-2'. + + +The DMD Compiler implementation of the D programming language: + - d/dmd/* + +Copyright (c) 1999-2010 by Digital Mars +All Rights Reserved +written by Walter Bright +http://www.digitalmars.com +License for redistribution is by either the Artistic License or +the GNU General Public License (v1). + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License is in `/usr/share/common-licenses/GPL', the Artistic +license in `/usr/share/common-licenses/Artistic'. + + +The Zlib data compression library: + - d/phobos/etc/c/zlib/* + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +The Phobos standard runtime library: + - d/phobos/* + +Unless otherwise marked within the file, each file in the source +is under the following licenses: + +Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com +Written by Walter Bright + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, in both source and binary form, subject to the following +restrictions: + + o The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + o Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + o This notice may not be removed or altered from any source + distribution. + +By plainly marking modifications, something along the lines of adding to each +file that has been changed a "Modified by Foo Bar" line +underneath the "Written by" line would be adequate. + +The libhsail-rt library is licensed under the following terms: + + Copyright (C) 2015-2017 Free Software Foundation, Inc. + Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com> + for General Processor Tech. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + +libhsail-rt/rt/fp16.c is licensed under the following terms: + + Copyright (C) 2008-2017 Free Software Foundation, Inc. + Contributed by CodeSourcery. + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. + +gcc/gm2: +Copyright (C) 2007-2019 Free Software Foundation, Inc. +Contributed by Gaius Mulley <gaius@glam.ac.uk>. + +This file is part of GNU Modula-2. + +GNU Modula-2 is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GNU Modula-2 is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +gcc/gm2/**/*.texi: +Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2012, 2013 Free Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + +gcc/gm2/gm2-coroutines: +Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +gcc/gm2/ulm-lib-gm2: +Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + +GNU Modula-2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +This file was originally part of the University of Ulm library + +Ulm's Modula-2 Library +Copyright (C) 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, +1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +by University of Ulm, SAI, D-89069 Ulm, Germany + +gcc/gm2/ulm-lib-gm2/std/M2RTS.mod: +gcc/gm2/ulm-lib-gm2/std/Storage.mod: +gcc/gm2/ulm-lib-gm2/std/RTExceptions.mod: + +Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +gcc/gm2/gm2-libs: +Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +./gm2-libs/cbuiltin.def: +./gm2-libs/MathLib0.def: +./gm2-libs/SYSTEM.def: +./gm2-libs/sckt.def: +./gm2-libs/Indexing.def: +./gm2-libs/Builtins.mod: +./gm2-libs/SFIO.mod: +./gm2-libs/MathLib0.mod: +./gm2-libs/gdbif.mod: +./gm2-libs/M2EXCEPTION.mod: +./gm2-libs/SFIO.def: +./gm2-libs/StringConvert.mod: +./gm2-libs/StringConvert.def: +./gm2-libs/config-host.in: +./gm2-libs/Indexing.mod: +./gm2-libs/errno.def: + +Copyright (C) 2001-2019 Free Software Foundation, Inc. +Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. + +GNU Modula-2 is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GNU Modula-2 is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +./gm2-libs/M2EXCEPTION.def: +Library module defined by the International Standard +Information technology - programming languages +BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language. + +Copyright ISO/IEC (International Organization for Standardization +and International Electrotechnical Commission) 1996, 1997, 1998, +1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + +gcc/gm2/gm2-libiberty/: +Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + +GNU Modula-2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +gcc/gm2/gm2-libs-iso/: +This has a mix of licenses, both LGPL-2.1 and GPL-3.0, plus the apparently +unmodified definition modules from ISO/IEC. + +gcc/gm2/gm2-libs-iso/*.def: + +Library module defined by the International Standard +Information technology - programming languages +BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language. + +Copyright ISO/IEC (International Organization for Standardization +and International Electrotechnical Commission) 1996, 1997, 1998, +1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + +gcc/gm2/gm2-libs-iso/*.def: + +Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + +gcc/gm2/gm2-libs-iso/*.def: +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +gcc/gm2/gm2-libs-iso/*.mod: + +Copyright (C) 2012 Free Software Foundation, Inc. + +GNU Modula-2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +gcc/gm2/gm2-libs-iso/*.mod: + +Copyright (C) 2009, 2010 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +gcc/gm2/gm2-libs-min/*: +Copyright (C) 2001-2019 Free Software Foundation, Inc. +mix of GPL-3.0 and LGPL-3.0 + +gcc/gm2/gm2-libs-pim/*: +Copyright (C) 2001-2019 Free Software Foundation, Inc. +mix of GPL-3.0 and LGPL-2.1/3 + +gcc/gm2/gm2-libs-ch/*: +Copyright (C) 2001-2019 Free Software Foundation, Inc. +mix of GPL-3.0 and LGPL-2.1/3 + +gcc/gm2/examples: +Copyright (C) 2005-2015 Free Software Foundation, Inc. +Mix of LGPL-2.1 and GPL-3.0. + +gcc/gm2/images: +GPL-3+ + +gcc/gm2/el/gm2-mode.el: +;; Everyone is granted permission to copy, modify and redistribute +;; GNU Emacs, but only under the conditions described in the +;; GNU Emacs General Public License. A copy of this license is +;; supposed to have been given to you along with GNU Emacs so you +;; can know your rights and responsibilities. It should be in a +;; file named COPYING. Among other things, the copyright notice +;; and this notice must be preserved on all copies. + +gcc/gm2/mc-boot/: +Copyright (C) 2001-2018 Free Software Foundation, Inc. +Contributed by Gaius Mulley <gaius@glam.ac.uk>. +Mix of GPL-3 and LGPL-2.1. + +gcc/testsuite/gm2/: +Copyright (C) 2001-2019 Free Software Foundation, Inc. +Mix of GPL-2+ and GPL-3+ + +libgm2: + +libgm2/libiso/: +Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +libgm2/libpim/: +Copyright (C) 2005-2014 Free Software Foundation, Inc. +Mix of LGPL-2.1, LGPL-3 and GPL-3. + +libgm2/liblog/: +Copyright (C) 2005-2018 Free Software Foundation, Inc. +Mix of LGPL-2.1 and LGPL-3. + +libgm2/libpth/: +Copyright: (C) 1999-2006 Ralf S. Engelschall <rse@gnu.org> +License: LGPL-2.1+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + +libgm2/libulm/: +Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + +GNU Modula-2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +libgm2/libcor/: +Copyright (C) 2005-2019 Free Software Foundation, Inc. +Contributed by Gaius Mulley <gaius@glam.ac.uk>. + +GNU Modula-2 is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GNU Modula-2 is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +libgm2/libmin/: +Copyright (C) 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + +GNU Modula-2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +libgm2/p2c/: +Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + +GNU Modula-2 is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GNU Modula-2 is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +newlib-X.Y.Z/: + +Upstream Authors: +newlib@sources.redhat.com +Jeff Johnston <jjohnstn@redhat.com> +Tom Fitzsimmons <fitzsim@redhat.com> + +The newlib subdirectory is a collection of software from several sources. +Each file may have its own copyright/license that is embedded in the source +file. + +This list documents those licenses which are more restrictive than +a BSD-like license or require the copyright notice +to be duplicated in documentation and/or other materials associated with +the distribution. Certain licenses documented here only apply to +specific targets. Certain clauses only apply if you are building the +code as part of your binary. + +Note that this list may omit certain licenses that +only pertain to the copying/modifying of the individual source code. +If you are distributing the source code, then you do not need to +worry about these omitted licenses, so long as you do not modify the +copyright information already in place. + +Parts of this work are licensed under the terms of the GNU General +Public License. On Debian systems, the complete text of this license +can be found in /usr/share/common-licenses/GPL. + +Parts of this work are licensed under the terms of the GNU Library +General Public License. On Debian systems, the complete text of this +license be found in /usr/share/common-licenses/LGPL. + +(1) University of California, Berkeley + +[1a] + +Copyright (c) 1990 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms are permitted +provided that the above copyright notice and this paragraph are +duplicated in all such forms and that any documentation, +and other materials related to such distribution and use +acknowledge that the software was developed +by the University of California, Berkeley. The name of the +University may not be used to endorse or promote products derived +from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +[1b] + +Copyright (c) 1990 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms are permitted +provided that the above copyright notice and this paragraph are +duplicated in all such forms and that any documentation, +advertising materials, and other materials related to such +distribution and use acknowledge that the software was developed +by the University of California, Berkeley. The name of the +University may not be used to endorse or promote products derived +from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +[1c] + +Copyright (c) 1981, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 +The Regents of the University of California. +All rights reserved. + +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. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + +[1d] + +Copyright (c) 1988, 1990, 1993 Regents of the University of California. +All rights reserved. + +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. +3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + +[1e] + +Copyright (c) 1982, 1986, 1989, 1991, 1993, 1994 +The Regents of the University of California. All rights reserved. +(c) UNIX System Laboratories, Inc. +All or some portions of this file are derived from material licensed +to the University of California by American Telephone and Telegraph +Co. or Unix System Laboratories, Inc. and are reproduced herein with +the permission of UNIX System Laboratories, Inc. + +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. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + +[1f] + +Copyright (c) 1987, 1988, 2000 Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms are permitted +provided that: (1) source distributions retain this entire copyright +notice and comment, and (2) distributions including binaries display +the following acknowledgement: ``This product includes software +developed by the University of California, Berkeley and its contributors'' +in the documentation or other materials provided with the distribution +and in all advertising materials mentioning features or use of this +software. Neither the name of the University nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +------------------------------------------------------------- + Please note that in some of the above alternate licenses, there is a + statement regarding that acknowledgement must be made in any + advertising materials for products using the code. This restriction + no longer applies due to the following license change: + + ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change + + In some cases the defunct clause has been removed in modified newlib code and + in some cases, the clause has been left as-is. +------------------------------------------------------------- + +(2) Cygwin (cygwin targets only) + +Copyright 2001 Red Hat, Inc. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. + +(3) David M. Gay at AT&T + +The author of this software is David M. Gay. + +Copyright (c) 1991 by AT&T. + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY +REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY +OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +(4) Advanced Micro Devices + +Copyright 1989, 1990 Advanced Micro Devices, Inc. + +This software is the property of Advanced Micro Devices, Inc (AMD) which +specifically grants the user the right to modify, use and distribute this +software provided this notice is not removed or altered. All other rights +are reserved by AMD. + +AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS +SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL +DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR +USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the 29K Technical Support Center at +800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or +0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. + +Advanced Micro Devices, Inc. +29K Support Products +Mail Stop 573 +5900 E. Ben White Blvd. +Austin, TX 78741 +800-292-9263 + +(5) C.W. Sandmann + +Copyright (C) 1993 C.W. Sandmann + +This file may be freely distributed as long as the author's name remains. + +(6) Eric Backus + +(C) Copyright 1992 Eric Backus + +This software may be used freely so long as this copyright notice is +left intact. There is no warrantee on this software. + +(7) Sun Microsystems + +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + +(8) Hewlett Packard + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +(9) Hans-Peter Nilsson + +Copyright (C) 2001 Hans-Peter Nilsson + +Permission to use, copy, modify, and distribute this software is +freely granted, provided that the above copyright notice, this notice +and the following disclaimer are preserved with no changes. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +(10) Stephane Carrez (m68hc11-elf/m68hc12-elf targets only) + +Copyright (C) 1999, 2000, 2001, 2002 Stephane Carrez (stcarrez@nerim.fr) + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(11) Christopher G. Demetriou + +Copyright (c) 2001 Christopher G. Demetriou +All rights reserved. + +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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +(12) SuperH, Inc. + +Copyright 2002 SuperH, Inc. All rights reserved + +This software is the property of SuperH, Inc (SuperH) which specifically +grants the user the right to modify, use and distribute this software +provided this notice is not removed or altered. All other rights are +reserved by SuperH. + +SUPERH MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO +THIS SOFTWARE. IN NO EVENT SHALL SUPERH BE LIABLE FOR INDIRECT, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM +THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the SuperH Support Center via +e-mail at softwaresupport@superh.com . + +SuperH, Inc. +405 River Oaks Parkway +San Jose +CA 95134 +USA + +(13) Royal Institute of Technology + +Copyright (c) 1999 Kungliga Tekniska Hgskolan +(Royal Institute of Technology, Stockholm, Sweden). +All rights reserved. + +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. + +3. Neither the name of KTH nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY KTH AND ITS 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 KTH OR ITS 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. + +(14) Alexey Zelkin + +Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> +All rights reserved. + +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 AUTHOR 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 AUTHOR 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. + +(15) Andrey A. Chernov + +Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia. +All rights reserved. + +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 AUTHOR ``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 REGENTS 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. + +(16) FreeBSD + +Copyright (c) 1997-2002 FreeBSD Project. +All rights reserved. + +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 AUTHOR 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 AUTHOR 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. + +(17) S. L. Moshier + +Author: S. L. Moshier. + +Copyright (c) 1984,2000 S.L. Moshier + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION +OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS +SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +(18) Citrus Project + +Copyright (c)1999 Citrus Project, +All rights reserved. + +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 AUTHOR 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 AUTHOR 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. + +(19) Todd C. Miller + +Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> +All rights reserved. + +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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. + +(20) DJ Delorie (i386) + +Copyright (C) 1991 DJ Delorie +All rights reserved. + +Redistribution and use in source and binary forms is permitted +provided that the above copyright notice and following paragraph are +duplicated in all such forms. + +This file is distributed WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +(21) Free Software Foundation LGPL License (*-linux* targets only) + + Copyright (C) 1990-1999, 2000, 2001 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + 02110-1301 USA + +(22) Xavier Leroy LGPL License (i[3456]86-*-linux* targets only) + +Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Library General Public License for more details. + +(23) Intel (i960) + +Copyright (c) 1993 Intel Corporation + +Intel hereby grants you permission to copy, modify, and distribute this +software and its documentation. Intel grants this permission provided +that the above copyright notice appears in all copies and that both the +copyright notice and this permission notice appear in supporting +documentation. In addition, Intel grants this permission provided that +you prominently mark as "not part of the original" any modifications +made to this software or documentation, and that the name of Intel +Corporation not be used in advertising or publicity pertaining to +distribution of the software or the documentation without specific, +written prior permission. + +Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR +IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY +OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or +representations regarding the use of, or the results of the use of, +the software and documentation in terms of correctness, accuracy, +reliability, currentness, or otherwise; and you rely on the software, +documentation and results solely at your own risk. + +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, +LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES +OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM +PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. + +(24) Hewlett-Packard (hppa targets only) + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +(25) Henry Spencer (only *-linux targets) + +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. + +(26) Mike Barcroft + +Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> +All rights reserved. + +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 AUTHOR 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 AUTHOR 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. + +(27) Konstantin Chuguev (--enable-newlib-iconv) + +Copyright (c) 1999, 2000 + Konstantin Chuguev. All rights reserved. + +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 AUTHOR 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 AUTHOR 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. + + iconv (Charset Conversion Library) v2.0 + +(27) Artem Bityuckiy (--enable-newlib-iconv) + +Copyright (c) 2003, Artem B. Bityuckiy, SoftMine Corporation. +Rights transferred to Franklin Electronic Publishers. + +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 AUTHOR 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 AUTHOR 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. + +(28) Red Hat Incorporated + +Unless otherwise stated in each remaining newlib file, the remaining +files in the newlib subdirectory default to the following copyright. +It should be noted that Red Hat Incorporated now owns copyrights +belonging to Cygnus Solutions and Cygnus Support. + +Copyright (c) 1994, 1997, 2001, 2002, 2003, 2004 Red Hat Incorporated. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + The name of Red Hat Incorporated may not be used to endorse + or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED 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. + + +-------------------------------------------------------------------------------- + +6. libLLVMGenXIntrinsics + MIT License + Copyright (c) 2020 Intel Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + + The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +7. libLLVMSPIRVLib + ============================================================================== + LLVM Release License + ============================================================================== + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. + + ============================================================================== + Copyrights and Licenses for Third Party Software Distributed with LLVM: + ============================================================================== + The LLVM software contains code written by third parties. Such software will + have its own individual LICENSE.TXT file in the directory in which it appears. + This file will describe the copyrights, license, and restrictions which apply + to that code. + + The disclaimer of warranty in the University of Illinois Open Source License + applies to all code in the LLVM Distribution, and nothing in any of the + other licenses gives permission to use the names of the LLVM Team or the + University of Illinois to endorse or promote products derived from this + Software. + + The following pieces of software have additional or alternate copyrights, + licenses, and/or restrictions: + + Program Directory + ------- --------- + Autoconf llvm/autoconf + llvm/projects/ModuleMaker/autoconf + Google Test llvm/utils/unittest/googletest + OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} + pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} + ARM contributions llvm/lib/Target/ARM/LICENSE.TXT + md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h + + +-------------------------------------------------------------------------------- + +Other names and brands may be claimed as the property of others. diff --git a/third-party-programs-OIDN.txt b/third-party-programs-OIDN.txt new file mode 100644 index 00000000..f3d76ae1 --- /dev/null +++ b/third-party-programs-OIDN.txt @@ -0,0 +1,645 @@ +Intel(R) Open Image Denoise Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license +terms. This third party software, even if included with the distribution of the +Intel software, may be governed by separate license terms, including without +limitation, third party license terms, other Intel software license terms, and +open source software license terms. These separate license terms govern your use +of the third party programs as set forth in the "third-party-programs.txt" or +other similarly named text file. + +Third party programs and their corresponding required notices and/or license +terms are listed below. + +-------------------------------------------------------------------------------- + +1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) + Copyright 2016-2023 Intel Corporation + + Intel(R) oneAPI Threading Building Blocks (oneTBB) + Copyright 2005-2023 Intel Corporation + + Intel® Embree (snippets) + Copyright Intel Corporation + + Intel® OSPRay (snippets) + Copyright Intel Corporation + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +2. PyTorch + + From PyTorch: + + Copyright (c) 2016- Facebook, Inc (Adam Paszke) + Copyright (c) 2014- Facebook, Inc (Soumith Chintala) + Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) + Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) + Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) + Copyright (c) 2011-2013 NYU (Clement Farabet) + Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) + Copyright (c) 2006 Idiap Research Institute (Samy Bengio) + Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + + From Caffe2: + + Copyright (c) 2016-present, Facebook Inc. All rights reserved. + + All contributions by Facebook: + Copyright (c) 2016 Facebook Inc. + + All contributions by Google: + Copyright (c) 2015 Google Inc. + All rights reserved. + + All contributions by Yangqing Jia: + Copyright (c) 2015 Yangqing Jia + All rights reserved. + + All contributions from Caffe: + Copyright(c) 2013, 2014, 2015, the respective contributors + All rights reserved. + + All other contributions: + Copyright(c) 2015, 2016 the respective contributors + All rights reserved. + + Caffe2 uses a copyright model similar to Caffe: each contributor holds + copyright over their contributions to Caffe2. The project versioning records + all such contribution and copyright details. If a contributor wants to further + mark their specific copyright on a particular contribution, they should + indicate their copyright solely in the commit message of the change when it is + committed. + + All rights reserved. + + +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. + +3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3. pytorch-msssim + Copyright (c) 2019 Gongfan Fang + + ROCmSoftwarePlatform/composable_kernel + Copyright (c) 2018- , Advanced Micro Devices, Inc. (Chao Liu, Jing Zhang) + Copyright (c) 2019- , Advanced Micro Devices, Inc. (Letao Qin, Qianfeng Zhang, Liang Huang, Shaojie Wang) + Copyright (c) 2022- , Advanced Micro Devices, Inc. (Anthony Chang, Chunyu Lai, Illia Silin, Adam Osewski, Poyen Chen, Jehandad Khan) + Copyright (c) 2019-2021, Advanced Micro Devices, Inc. (Hanwen Chang) + Copyright (c) 2019-2020, Advanced Micro Devices, Inc. (Tejash Shah) + Copyright (c) 2020 , Advanced Micro Devices, Inc. (Xiaoyan Zhou) + Copyright (c) 2021-2022, Advanced Micro Devices, Inc. (Jianfeng Yan) + Copyright (c) 2018-2022, Advanced Micro Devices, Inc. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +4. Catch2 + Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +5. CUTLASS + Copyright (c) 2017 - 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +SPDX-License-Identifier: BSD-3-Clause + +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. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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. + +-------------------------------------------------------------------------------- + +6. oneAPI Data Parallel C++ Compiler + Copyright Intel Corporation + +============================================================================== +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +-------------------------------------------------------------------------------- + +The following third party programs have their own third party programs. These +additional third party program files are as follows: + +1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) + ./third-party-programs-oneDNN.txt + +2. Intel(R) oneAPI Threading Building Blocks (oneTBB) + ./third-party-programs-oneTBB.txt + +3. oneAPI DPC++ Compiler + ./third-party-programs-DPCPP.txt + +-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/third-party-programs-OSPRay.txt b/third-party-programs-OSPRay.txt index 89da5461..d0e54d65 100644 --- a/third-party-programs-OSPRay.txt +++ b/third-party-programs-OSPRay.txt @@ -29,6 +29,9 @@ terms are listed below. Intel(R) oneAPI Threading Building Blocks (oneTBB) Copyright 2005 Intel Corporation + Intel(R) Implicit SPMD Program Compiler (ISPC) + Copyright 2011 Intel Corporation + Apache License Version 2.0 January 2004 http://www.apache.org/licenses/ @@ -388,6 +391,7 @@ use. For further information on export restrictions, visit www.microsoft.com/exporting. -------------------------------------------------------------------------------- + 7. Google Snappy Copyright 2011, Google Inc. @@ -444,6 +448,725 @@ Some of the benchmark data in testdata/ is licensed differently: (http://www.gutenberg.org/ebooks/53). -------------------------------------------------------------------------------- + +8. oneAPI DPC++ Compiler + https://github.com/intel/llvm/ + + Apache License 2.0 with LLVM Exceptions + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +-------------------------------------------------------------------------------- + +9. Intel(R) oneAPI DPC++/C++ Compiler + +Intel End User License Agreement for Developer Tools (Version October 2021) + + + +IMPORTANT NOTICE - PLEASE READ AND AGREE BEFORE DOWNLOADING, INSTALLING, COPYING +OR USING + +This Agreement is between you, or the company or other legal entity that you +represent and warrant you have the legal authority to bind, (each, "You" or +"Your") and Intel Corporation and its subsidiaries (collectively, "Intel") +regarding Your use of the Materials. By downloading, installing, copying or +using the Materials, You agree to be bound by the terms of this Agreement. If +You do not agree to the terms of this Agreement, or do not have legal authority +or required age to agree to them, do not download, install, copy or use the +Materials. + + + +LICENSE DEFINITIONS. + + + +A. "Cloud Provider" means a third party service provider offering a +cloud-based platform, infrastructure, application or storage services, such as +Microsoft Azure or Amazon Web Services, which You may only utilize to host the +Materials subject to the restrictions set forth in Section 2.3 B. + + + +B. "Derivative Work" means a derivative work, as defined in 17 U.S.C. § 101, +of the Source Code. + + + +C. "Executable Code" means computer programming code in binary form suitable +for machine execution by a processor without the intervening steps of +interpretation or compilation. + + + +D. "Materials" mean the software, documentation, the software product serial +number, and other collateral, including any updates, made available to You by +Intel under this Agreement. Materials include Redistributables, Executable Code, +Source Code, Sample Source Code, and Pre-Release Materials, but do not include +Third Party Software. + + + +E. "Pre-Release Materials" mean the Materials, or portions of the Materials, +that are identified (in the product release notes, on Intel's download website +for the Materials or elsewhere) or labeled as pre-release, prototype, alpha or +beta code and, as such, are deemed to be pre-release code (i) which may not be +fully functional or tested and may contain bugs or errors; (ii) which Intel may +substantially modify in its development of a production version; or (iii) for +which Intel makes no assurances that it will ever develop or make a production +version generally available. Pre-Release Materials are subject to the terms of +Section 3.2. + + + +F. "Reciprocal Open Source Software" means any software that is subject to a +license which requires that (i) it must be distributed in source code form; (ii) +it must be licensed under the same open source license terms; and (iii) its +derivative works must be licensed under the same open source license terms. +Examples of this type of license are the GNU General Public License or the +Mozilla Public License. + + + +G. "Redistributables" mean the files (if any) listed in the "redist.txt," +"redist-rt.txt" or similarlynamed text files that may be included in the +Materials. Redistributables include Sample Source Code. + + + +H. "Sample Source Code" means those portions of the Materials that are Source +Code and are identified as sample code. Sample Source Code may not have been +tested or validated by Intel and is provided purely as a programming example. + + + +I. "Source Code" means the software portion of the Materials provided in +human readable format. + + + +J. "Third Party Software" mean the files (if any) listed in the +"third-party-software.txt" or other similarly-named text file that may be +included in the Materials for the applicable software. Third Party Software is +subject to the terms of Section 2.2. + + + +K. "Your Product" means one or more applications, products or projects +developed by or for You using the Materials. + + + +2. LICENSE GRANTS. + + + +2.1 License to the Materials. Subject to the terms and conditions of this +Agreement, Intel grants You a non-exclusive, worldwide, non-assignable, +non-sublicensable, limited right and license under its copyrights, to: + + + +A. reproduce internally a reasonable number of copies of the Materials for +Your personal or business use; + + + +B. use the Materials solely for Your personal or business use to develop Your +Product, in accordance with the documentation included as part of the Materials; + + + +C. modify or create Derivative Works only of the Redistributables, or any +portions, that are provided to You in Source Code; + + + +D. distribute (directly and through Your distributors, resellers, and other +channel partners, if applicable), the Redistributables, including any +modifications to or Derivative Works of the Redistributables or any portions +made pursuant to Section 2.1.C subject to the following conditions: + + + +(1) Any distribution of the Redistributables must only be as part of Your +Product which must add significant primary functionality different than that of +the Redistributables themselves; + + + +(2) You must only distribute the Redistributables originally provided to You +by Intel only in Executable Code subject to a license agreement that prohibits +reverse engineering, decompiling or disassembling the Redistributables; + + + +(3) This distribution right includes a limited right to sublicense only the +Intel copyrights in the Redistributables and only to the extent necessary to +perform, display, and distribute the Redistributables (including Your +modifications and Derivative Works of the Redistributables provided in Source +Code) solely as incorporated in Your Product; and + + + +(4) You: (i) will be solely responsible to Your customers for any update, +support obligation or other obligation or liability which may arise from the +distribution of Your Product, (ii) will not make any statement that Your Product +is "certified" or that its performance is guaranteed by Intel or its suppliers, +(iii) will not use Intel's or its suppliers' names or trademarks to market Your +Product, (iv) will comply with any additional restrictions which are included in +the text files with the Redistributables and in Section 3 below, (v) will +indemnify, hold harmless, and defend Intel and its suppliers from and against +any claims or lawsuits, costs, damages, and expenses, including attorney's fees, +that arise or result from (a) Your modifications or Derivative Works of the +Materials or (b) Your distribution of Your Product. + + + +2.2 Third Party Software. Third Party Software, even if included with the +distribution of the Materials, may be governed by separate license terms, +including without limitation, third party license terms, open source software +notices and terms, and/or other Intel software license terms. These separate +license terms solely govern Your use of the Third Party Software. + + + +2.3 Third Party Use. + +A. If You are an entity, Your contractors may use the Materials under the +license specified in Section 2, provided: (i) their use of the Materials is +solely on behalf of and in support of Your business, (ii) they agree to the +terms and conditions of this Agreement, and (iii) You are solely responsible for +their use, misuse or disclosure of the Materials. + + + +B. You may utilize a Cloud Provider to host the Materials for You, provided: +(i) the Cloud Provider may only host the Materials for Your exclusive use and +may not use the Materials for any other purpose whatsoever, including the +restriction set forth in Section 3.1(xi); (ii) the Cloud Provider's use of the +Materials must be solely on behalf of and in support of Your Product, and (iii) +You will indemnify, hold harmless, and defend Intel and its suppliers from and +against any claims or lawsuits, costs, damages, and expenses, including +attorney's fees, that arise or result from Your Cloud Provider's use, misuse or +disclosure of the Materials. + + + +3. LICENSE CONDITIONS. + + + +3.1 Restrictions. Except as expressly provided in this Agreement, You may +NOT: (i) use, reproduce, disclose, distribute, or publicly display the +Materials; (ii) share, publish, rent or lease the Materials to any third party; +(iii) assign this Agreement or transfer the Materials; (iv) modify, adapt, or +translate the Materials in whole or in part; (v) reverse engineer, decompile, or +disassemble the Materials, or otherwise attempt to derive the source code for +the software; (vi) work around any technical limitations in the Materials; (vii) +distribute, sublicense or transfer any Source Code, modifications or Derivative +Works of any Source Code to any third party; (viii) remove, minimize, block or +modify any notices of Intel or its suppliers in the Materials; (ix) include the +Redistributables in malicious, deceptive, or unlawful programs or products or +use the Materials in any way that is against the law; (x) modify, create a +Derivative Work, link, or distribute the Materials so that any part of it +becomes Reciprocal Open Source Software; (xi) use the Materials directly or +indirectly for SaaS services or service bureau purposes (i.e., a service that +allows use of or access to the Materials by a third party as part of that +service, such as the salesforce.com service business model). + + + +3.2 Pre-Release Materials. If You receive Pre-Release Materials, You may +reproduce a reasonable number of copies and use the Pre-Release Materials for +evaluation and testing purposes only. You may not (i) modify or incorporate the +Pre-Release Materials into Your Product; (ii) continue to use the Pre-Release +Materials once a commercial version is released; or (iii) disclose to any third +party any benchmarks, performance results, or other information relating to the +Pre-Release Materials. Intel may waive these restrictions in writing at its sole +discretion; however, if You decide to use the Pre-Release Materials in Your +Product (even with Intel's waiver), You acknowledge and agree that You are fully +responsible for any and all issues that result from such use. + + + +3.3 Safety-Critical, and Life-Saving Applications; Indemnity. The Materials +may provide information relevant to safety-critical applications +("Safety-Critical Applications") to allow compliance with functional safety +standards or requirements. You acknowledge and agree that safety is Your +responsibility. To the extent You use the Materials to create, or as part of, +products used in Safety-Critical Applications, it is Your responsibility to +design, manage, and ensure that there are system-level safeguards to anticipate, +monitor, and control system failures, and You agree that You are solely +responsible for all applicable regulatory standards and safety-related +requirements concerning Your use of the Materials in Safety Critical +Applications. + + + +Should You use the Materials for Safety-Critical Applications or in any type of +a system or application in which the failure of the Materials could create a +situation where personal injury or death may occur (e.g., medical systems, +life-sustaining or life-saving systems) ("Life-Saving Applications"), You agree +to indemnify, defend, and hold Intel and its representatives harmless against +any claims or lawsuits, costs, damages, and expenses, including reasonable +attorney fees, arising in any way out of Your use of the Materials in +Safety-Critical Applications or Life-Saving Applications and claims of product +liability, personal injury or death associated with those applications; even if +such claims allege that Intel was negligent or strictly liable regarding the +design or manufacture of the Materials or its failure to warn regarding the +Materials. + + + +3.4 Media Format Codecs and Digital Rights Management. You acknowledge and +agree that Your use of the Materials or distribution of the Redistributables +with Your Product as permitted by this Agreement may require You to procure +license(s) from third parties that may hold intellectual property rights +applicable to any media decoding, encoding or transcoding technology (e.g., the +use of an audio or video codec) and/or digital rights management capabilities of +the Materials, if any. Should any such additional licenses be required, You are +solely responsible for obtaining any such licenses and agree to obtain any such +licenses at Your own expense. + + + +4. DATA COLLECTION AND PRIVACY. + + + +4.1 Data Collection. The Materials may generate and collect anonymous data +and/or provisioning data about the Materials and/or the development environment +and transmit the data to Intel as a one-time event during installation. Optional +data may also be collected by the Materials, however, You will be provided +notice of the request to collect optional data and no optional data will be +collected without Your consent. All data collection by Intel is performed +pursuant to relevant privacy laws, including notice and consent requirements. + + + +4.2 Intel's Privacy Notice. Intel is committed to respecting Your privacy. +To learn more about Intel's privacy practices, please visit +http://www.intel.com/privacy. + + + +5. OWNERSHIP. Title to the Materials and all copies remain with Intel or its +suppliers. The Materials are protected by intellectual property rights, +including without limitation, United States copyright laws and international +treaty provisions. You will not remove any copyright or other proprietary +notices from the Materials. Except as expressly provided herein, no license or +right is granted to You directly or by implication, inducement, estoppel or +otherwise; specifically, Intel does not grant any express or implied right to +You under Intel patents, copyrights, trademarks, or trade secrets. + + + +6. NO WARRANTY AND NO SUPPORT. + + + +6.1 No Warranty. Disclaimer. Intel disclaims all warranties of any kind and +the terms and remedies provided in this Agreement are instead of any other +warranty or condition, express, implied or statutory, including those regarding +merchantability, fitness for any particular purpose, non-infringement or any +warranty arising out of any course of dealing, usage of trade, proposal, +specification or sample. Intel does not assume (and does not authorize any +person to assume on its behalf) any liability. + + + +6.2 No Support; Priority Support. Intel may make changes to the Materials, +or to items referenced therein, at any time without notice, but is not obligated +to support, update or provide training for the Materials under the terms of this +Agreement. Intel offers free community and paid priority support options. More +information on these support options can be found at: + +https://software.intel.com/content/www/us/en/develop/support/priority-support.html. + + + +7. LIMITATION OF LIABILITY. + + + +7.1 Intel will not be liable for any of the following losses or damages +(whether such losses or damages were foreseen, foreseeable, known or otherwise): +(i) loss of revenue; (ii) loss of actual or anticipated profits; (iii) loss of +the use of money; (iv) loss of anticipated savings; (v) loss of business; (vi) +loss of opportunity; (vii) loss of goodwill; (viii) loss of use of the +Materials; (ix) loss of reputation; (x) loss of, damage to, or corruption of +data; or (xi) any indirect, incidental, special or consequential loss of damage +however caused (including loss or damage of the type specified in this Section +7). + + + +7.2 Intel's total cumulative liability to You, including for direct damages +for claims relating to this Agreement, and whether for breach of contract, +negligence, or for any other reason, will not exceed $100. + + + +7.3 You acknowledge that the limitations of liability provided in this +Section 7 are an essential part of this Agreement. You agree that the +limitations of liability provided in this Agreement with respect to Intel will +be conveyed to and made binding upon any customer of Yours that acquires the +Redistributables. + + + +8. USER SUBMISSIONS. Should you provide Intel with comments, modifications, +corrections, enhancements or other input ("Feedback") related to the Materials, +Intel will be free to use, disclose, reproduce, license or otherwise distribute +or exploit the Feedback in its sole discretion without any obligations or +restrictions of any kind, including without limitation, intellectual property +rights or licensing obligations. If You wish to provide Intel with information +that You intend to be treated as confidential information, Intel requires that +such confidential information be provided pursuant to a non-disclosure agreement +("NDA"); please contact Your Intel representative to ensure the proper NDA is in +place. + + + +9. NON-DISCLOSURE. Information provided by Intel to You may include +information marked as confidential. You must treat such information as +confidential under the terms of the applicable NDA between Intel and You. If You +have not entered into an NDA with Intel, You must not disclose, distribute or +make use of any information marked as confidential, except as expressly +authorized in writing by Intel. Intel retains all rights in and to its +confidential information specifications, designs, engineering details, +discoveries, inventions, patents, copyrights, trademarks, trade secrets, and +other proprietary rights relating to the Materials. Any breach by You of the +confidentiality obligations provided for in this Section 9 will cause +irreparable injury to Intel for which money damages may be inadequate to +compensate Intel for losses arising from such a breach. Intel may obtain +equitable relief, including injunctive relief, if You breach or threaten to +breach Your confidentiality obligations. + + + +10. TERM AND TERMINATION. This Agreement becomes effective on the date You +accept this Agreement and will continue until terminated as provided for in this +Agreement. The term for any Pre-Release Materials terminates upon release of a +commercial version. This Agreement will terminate if You are in breach of any of +its terms and conditions. Upon termination, You will promptly destroy the +Materials and all copies. In the event of termination of this Agreement, Your +license to any Redistributables distributed by You in accordance with the terms +and conditions of this Agreement, prior to the effective date of such +termination, will survive any such termination of this Agreement. Sections 1, +2.1.D(4)(v), 2.2, 2.3.A(iii), 2.3.B(iii), 3.3, 5, 6, 7, 8, 9, 10 (with respect +to these survival provisions in the last sentence), and 12 will survive +expiration or termination of this Agreement. + + + +11. U.S. GOVERNMENT RESTRICTED RIGHTS. The technical data and computer software +covered by this license is a "Commercial Item," as such term is defined by the +FAR 2.101 (48 C.F.R. 2.101) and is "commercial computer software" and +"commercial computer software documentation" as specified under FAR 12.212 (48 +C.F.R. 12.212) or DFARS 227.7202 (48 C.F.R. 227.7202), as applicable. This +commercial computer software and related documentation is provided to end users +for use by and on behalf of the U.S. Government with only those rights as are +granted to all other end users pursuant to the terms and conditions of this +Agreement. + + + +12. GENERAL PROVISIONS. + + + +12.1 ENTIRE AGREEMENT. This Agreement contains the complete and exclusive +agreement and understanding between the parties concerning the subject matter of +this Agreement, and supersedes all prior and contemporaneous proposals, +agreements, understanding, negotiations, representations, warranties, +conditions, and communications, oral or written, between the parties relating to +the same subject matter. Each party acknowledges and agrees that in entering +into this Agreement it has not relied on, and will not be entitled to rely on, +any oral or written representations, warranties, conditions, understanding, or +communications between the parties that are not expressly set forth in this +Agreement. The express provisions of this Agreement control over any course of +performance, course of dealing, or usage of the trade inconsistent with any of +the provisions of this Agreement. The provisions of this Agreement will prevail +notwithstanding any different, conflicting, or additional provisions that may +appear on any purchase order, acknowledgement, invoice, or other writing issued +by either party in connection with this Agreement. No modification or amendment +to this Agreement will be effective unless in writing and signed by authorized +representatives of each party, and must specifically identify this Agreement by +its title and version (e.g., "Intel End User License Agreement for Developer +Tools (Version October 2021)"); except that Intel may make changes to this +Agreement as it distributes new versions of the Materials. When changes are +made, Intel will make a new version of the Agreement available on its website. +If You received a copy of this Agreement translated into another language, the +English language version of this Agreement will prevail in the event of any +conflict between versions. + + + +12.2 EXPORT. You acknowledge that the Materials and all related technical +information are subject to export controls and you agree to comply with all laws +and regulations of the United States and other applicable governments governing +export, re-export, import, transfer, distribution, and use of the Materials. In +particular, but without limitation, the Materials may not be exported or +re-exported (i) into any U.S. embargoed countries or (ii) to any person or +entity listed on a denial order published by the U.S. government or any other +applicable governments. By using the Materials, You represent and warrant that +You are not located in any such country or on any such list. You also agree that +You will not use the Materials for, or sell or transfer them to a third party +who is known or suspected to be involved in, any purposes prohibited by the U.S. +government or other applicable governments, including, without limitation, the +development, design, manufacture, or production of nuclear, missile, chemical or +biological weapons. + + + +12.3 GOVERNING LAW, JURISDICTION, AND VENUE. All disputes arising out of or +related to this Agreement, whether based on contract, tort, or any other legal +or equitable theory, will in all respects be governed by, and construed and +interpreted under, the laws of the United States of America and the State of +Delaware, without reference to conflict of laws principles. The parties agree +that the United Nations Convention on Contracts for the International Sale of +Goods (1980) is specifically excluded from and will not apply to this Agreement. +All disputes arising out of or related to this Agreement, whether based on +contract, tort, or any other legal or equitable theory, will be subject to the +exclusive jurisdiction of the courts of the State of Delaware or of the Federal +courts sitting in that State. Each party submits to the personal jurisdiction of +those courts and waives all objections to that jurisdiction and venue for those +disputes. + + + +12.4 SEVERABILITY. The parties intend that if a court holds that any +provision or part of this Agreement is invalid or unenforceable under applicable +law, the court will modify the provision to the minimum extent necessary to make +it valid and enforceable, or if it cannot be made valid and enforceable, the +parties intend that the court will sever and delete the provision or part from +this Agreement. Any change to or deletion of a provision or part of this +Agreement under this Section will not affect the validity or enforceability of +the remainder of this Agreement, which will continue in full force and effect. + +-------------------------------------------------------------------------------- + The following third party programs have their own third party programs. These additional third party program files are as follows: @@ -451,6 +1174,9 @@ additional third party program files are as follows: 2. Open Image Denoise: ./third-party-programs-OIDN.txt 3. Open VKL: ./third-party-programs-OpenVKL.txt 4. oneAPI Threading Building Blocks: ./third-party-programs-oneTBB.txt +5. Implicit SPMD Program Compiler: ./third-party-programs-ISPC.txt +6. oneAPI DPC++ Compiler: ./third-party-programs-DPCPP.txt +7. Intel(R) oneAPI DPC++/C++ Compiler: ./third-party-programs-oneAPI-DPCPP.txt -------------------------------------------------------------------------------- diff --git a/third-party-programs-OpenVKL.txt b/third-party-programs-OpenVKL.txt new file mode 100644 index 00000000..af1b375e --- /dev/null +++ b/third-party-programs-OpenVKL.txt @@ -0,0 +1,716 @@ +Intel(R) Open Volume Kernel Library Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license terms. +This third party software, even if included with the distribution of the Intel +software, may be governed by separate license terms, including without +limitation, third party license terms, other Intel software license terms, and +open source software license terms. These separate license terms govern your use +of the third party programs as set forth in the "third-party-programs.txt" or +other similarly- named text file. + +Third party programs and their corresponding required notices and/or license +terms are listed below. + +-------------------------------------------------------------------------------- + +1. Boost C++ Libraries + Copyright Beman Dawes, David Abrahams, 1998-2005. + Copyright Rene Rivera 2004-2005. + + Catch2 + Copyright 2010 Two Blue Cubes Ltd + + Boost Software License - Version 1.0 - August 17th, 2003 + + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: + + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, must + be included in all copies of the Software, in whole or in part, and all + derivative works of the Software, unless such copies or derivative works are + solely in the form of machine-executable object code generated by a source + language processor. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +2. IlmBase (part of OpenEXR) + Copyright (c) 2006-2019 OpenEXR a Series of LF Projects, LLC. All rights + reserved. + + BSD 3-Clause "New" or "Revised" License + + 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. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. THIS SOFTWARE IS + PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL THE COPYRIGHT 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. + +-------------------------------------------------------------------------------- + +3. Dear ImGui + Copyright (c) 2014-2020 Omar Cornut + + half + Copyright (c) 2012-2021 Christian Rau <rauy@users.sourceforge.net> + + SSE2NEON + + The MIT License (MIT) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +4. Embree + Copyright 2009 Intel Corporation + + Google Benchmark + Copyright 2014 Google Inc. All rights reserved. + + OSPRay + Copyright 2009 Intel Corporation + + Threading Building Blocks (oneTBB) + Copyright 2005 Intel Corporation + + Apache License Version 2.0 + January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. "License" shall mean the terms and conditions for use, + reproduction, and distribution as defined by Sections 1 through 9 of this + document. + + "Licensor" shall mean the copyright owner or entity authorized by the + copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other + entities that control, are controlled by, or are under common control with + that entity. For the purposes of this definition, "control" means (i) the + power, direct or indirect, to cause the direction or management of such + entity, whether by contract or otherwise, or (ii) ownership of fifty percent + (50%) or more of the outstanding shares, or (iii) beneficial ownership of + such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising + permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation source, and + configuration files. + + "Object" form shall mean any form resulting from mechanical transformation + or translation of a Source form, including but not limited to compiled + object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, + made available under the License, as indicated by a copyright notice that is + included in or attached to the work (an example is provided in the Appendix + below). + + "Derivative Works" shall mean any work, whether in Source or Object form, + that is based on (or derived from) the Work and for which the editorial + revisions, annotations, elaborations, or other modifications represent, as a + whole, an original work of authorship. For the purposes of this License, + Derivative Works shall not include works that remain separable from, or + merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof. + + "Contribution" shall mean any work of authorship, including the original + version of the Work and any modifications or additions to that Work or + Derivative Works thereof, that is intentionally submitted to Licensor for + inclusion in the Work by the copyright owner or by an individual or Legal + Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, "submitted" means any form of electronic, + verbal, or written communication sent to the Licensor or its + representatives, including but not limited to communication on electronic + mailing lists, source code control systems, and issue tracking systems that + are managed by, or on behalf of, the Licensor for the purpose of discussing + and improving the Work, but excluding communication that is conspicuously + marked or otherwise designated in writing by the copyright owner as "Not a + Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on + behalf of whom a Contribution has been received by Licensor and subsequently + incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly perform, + sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily + infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. + If You institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or contributory + patent infringement, then any patent licenses granted to You under this + License for that Work shall terminate as of the date such litigation is + filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, and + in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating + that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices from + the Source form of the Work, excluding those notices that do not pertain to + any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable copy + of the attribution notices contained within such NOTICE file, excluding + those notices that do not pertain to any part of the Derivative Works, in at + least one of the following places: within a NOTICE text file distributed as + part of the Derivative Works; within the Source form or documentation, if + provided along with the Derivative Works; or, within a display generated by + the Derivative Works, if and wherever such third-party notices normally + appear. The contents of the NOTICE file are for informational purposes only + and do not modify the License. You may add Your own attribution notices + within Derivative Works that You distribute, alongside or as an addendum to + the NOTICE text from the Work, provided that such additional attribution + notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated in + this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to the + Licensor shall be under the terms and conditions of this License, without + any additional terms or conditions. Notwithstanding the above, nothing + herein shall supersede or modify the terms of any separate license agreement + you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, except + as required for reasonable and customary use in describing the origin of the + Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in + writing, Licensor provides the Work (and each Contributor provides its + Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied, including, without limitation, any + warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or + FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining + the appropriateness of using or redistributing the Work and assume any risks + associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether + in tort (including negligence), contract, or otherwise, unless required by + applicable law (such as deliberate and grossly negligent acts) or agreed to + in writing, shall any Contributor be liable to You for damages, including + any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or inability + to use the Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all other + commercial damages or losses), even if such Contributor has been advised of + the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work + or Derivative Works thereof, You may choose to offer, and charge a fee for, + acceptance of support, warranty, indemnity, or other liability obligations + and/or rights consistent with this License. However, in accepting such + obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if You + agree to indemnify, defend, and hold each Contributor harmless for any + liability incurred by, or claims asserted against, such Contributor by + reason of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following boilerplate + notice, with the fields enclosed by brackets "[]" replaced with your own + identifying information. (Don't include the brackets!) The text should be + enclosed in the appropriate comment syntax for the file format. We also + recommend that a file or class name and description of purpose be included + on the same "printed page" as the copyright notice for easier identification + within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); you may not + use this file except in compliance with the License. You may obtain a copy + of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + License for the specific language governing permissions and limitations + under the License. + +-------------------------------------------------------------------------------- + +5. GLFW + Copyright (c) 2002-2006 Marcus Geelnard + Copyright (c) 2006-2019 Camilla Löwy + + zlib + Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler + + zlib License + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the + use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be appreciated + but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + +-------------------------------------------------------------------------------- + +6. OpenVDB + Copyright Contributors to the OpenVDB Project + + Mozilla Public License Version 2.0 + + 1. Definitions + + 1.1. "Contributor" means each individual or legal entity that creates, + contributes to the creation of, or owns Covered Software. + + 1.2. "Contributor Version" means the combination of the Contributions of + others (if any) used by a Contributor and that particular Contributor's + Contribution. + + 1.3. "Contribution" means Covered Software of a particular Contributor. + + 1.4. "Covered Software" means Source Code Form to which the initial + Contributor has attached the notice in Exhibit A, the Executable Form of + such Source Code Form, and Modifications of such Source Code Form, in each + case including portions thereof. + + 1.5. "Incompatible With Secondary Licenses" means + + (a) that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a Secondary + License. + + 1.6. "Executable Form" means any form of the work other than Source Code + Form. + + 1.7. "Larger Work" means a work that combines Covered Software with other + material, in a separate file or files, that is not Covered Software. + + 1.8. "License" means this document. + + 1.9. "Licensable" means having the right to grant, to the maximum extent + possible, whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + + 1.10. "Modifications" means any of the following: + + (a) any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + (b) any new file in Source Code Form that contains any Covered Software. + + 1.11. "Patent Claims" of a Contributor means any patent claim(s), including + without limitation, method, process, and apparatus claims, in any patent + Licensable by such Contributor that would be infringed, but for the grant of + the License, by the making, using, selling, offering for sale, having made, + import, or transfer of either its Contributions or its Contributor Version. + + 1.12. "Secondary License" means either the GNU General Public License, + Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU + Affero General Public License, Version 3.0, or any later versions of those + licenses. + + 1.13. "Source Code Form" means the form of the work preferred for making + modifications. + + 1.14. "You" (or "Your") means an individual or a legal entity exercising + rights under this License. For legal entities, "You" includes any entity + that controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct or + indirect, to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent (50%) of + the outstanding shares or beneficial ownership of such entity. + + 2. License Grants and Conditions + + 2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive + license: + + (a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, modify, + display, perform, distribute, and otherwise exploit its Contributions, + either on an unmodified basis, with Modifications, or as part of a Larger + Work; and + + (b) under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions or + its Contributor Version. + + 2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first + distributes such Contribution. + + 2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + (a) for any code that a Contributor has removed from Covered Software; or + + (b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + (c) under Patent Claims infringed by Covered Software in the absence of its + Contributions. This License does not grant any rights in the trademarks, + service marks, or logos of any Contributor (except as may be necessary to + comply with the notice requirements in Section 3.4). + + 2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + + 2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the rights + to its Contributions conveyed by this License. + + 2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + + 2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + 3. Responsibilities + + 3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients' rights in the Source Code Form. + + 3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + (a) such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost of + distribution to the recipient; and + + (b) You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for the + Executable Form does not attempt to limit or alter the recipients' rights in + the Source Code Form under this License. + + 3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of such + Secondary License(s), so that the recipient of the Larger Work may, at their + option, further distribute the Covered Software under the terms of either + this License or such Secondary License(s). + + 3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered Software, + except that You may alter any license notices to the extent required to + remedy known factual inaccuracies. + + 3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any liability + incurred by such Contributor as a result of warranty, support, indemnity or + liability terms You offer. You may include additional disclaimers of + warranty and limitations of liability specific to any jurisdiction. + + 4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this + License to the maximum extent possible; and (b) describe the limitations and + the code they affect. Such description must be placed in a text file + included with all distributions of the Covered Software under this License. + Except to the extent prohibited by statute or regulation, such description + must be sufficiently detailed for a recipient of ordinary skill to be able + to understand it. + + 5. Termination + + 5.1. The rights granted under this License will terminate automatically if + You fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor are + reinstated (a) provisionally, unless and until such Contributor explicitly + and finally terminates Your grants, and (b) on an ongoing basis, if such + Contributor fails to notify You of the non-compliance by some reasonable + means prior to 60 days after You have come back into compliance. Moreover, + Your grants from a particular Contributor are reinstated on an ongoing basis + if such Contributor notifies You of the non-compliance by some reasonable + means, this is the first time You have received notice of non-compliance + with this License from such Contributor, and You become compliant prior to + 30 days after Your receipt of the notice. + + 5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or indirectly + infringes any patent, then the rights granted to You by any and all + Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + + 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end + user license agreements (excluding distributors and resellers) which have + been validly granted by You or Your distributors under this License prior to + termination shall survive termination. + + 6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of + this License. No use of any Covered Software is authorized under this + License except under this disclaimer. + + 7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + + 8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party's ability to bring cross-claims or counter-claims. + + 9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to + construe this License against a Contributor. + + 10. Versions of the License + + 10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + + 10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license steward. + + 10.3. Modified Versions + + If you create software not governed by this License, and you want to create + a new license for such software, you may create and use a modified version + of this License if you rename the license and remove any references to the + name of the license steward (except to note that such modified license + differs from this License). + + 10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses + + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + + Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at http://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, + then You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a + notice. + + You may add additional accurate notices of copyright ownership. + + Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible With Secondary Licenses", as defined + by the Mozilla Public License, v. 2.0. + +-------------------------------------------------------------------------------- + +7. C-Blosc + Copyright (C) 2009-2018 Francesc Alted <francesc@blosc.org> + Copyright (C) 2019-present Blosc Development team <blosc@blosc.org> + +BSD-3-Clause (modified) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Francesc Alted nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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. + +-------------------------------------------------------------------------------- + +The following third party programs have their own third party programs. These +additional third party program files are as follows: + +1. Embree: ./third-party-programs-Embree.txt +2. OSPRay: ./third-party-programs.txt +3. Threading Building Blocks (TBB): ./third-party-programs-oneTBB.txt + +-------------------------------------------------------------------------------- + +Other names and brands may be claimed as the property of others. diff --git a/third-party-programs-oneAPI-DPCPP.txt b/third-party-programs-oneAPI-DPCPP.txt new file mode 100644 index 00000000..9898dfce --- /dev/null +++ b/third-party-programs-oneAPI-DPCPP.txt @@ -0,0 +1,997 @@ +Intel(R) 2023.0 oneAPI DPC++/C++/Fortran Compiler Third Party Programs File + +This file is the "third-party-programs.txt" file specified in the associated Intel end user license agreement for the Intel software you are licensing. + +Third party programs and their corresponding required notices and/or license terms are listed below. + +----------------------------------------------------------------- + +1. Khronos Group - OpenCL header + Copyright (c) 2008-2020 The Khronos Group Inc. + + Khronos OpenCL ICD Loader + Copyright (c) 2020 The Khronos Group Inc. + + Threading Building Blocks + Copyright 2020 Intel Corporation + + Mentor Graphics Algorithmic C Types + Copyright 2008-2016, Mentor Graphics Corporation + +Apache License +Version 2.0, January 2004 + +http://www.apache.org/licenses/ +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +----------------------------------------------------------------- +2. Khronos Group - SPIRV-LLVM-Translator + +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Autoconf llvm/autoconf + llvm/projects/ModuleMaker/autoconf +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h + +----------------------------------------------------------------- + +3. llvm-project llvm-project + +============================================================================== +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +----------------------------------------------------------------- + +4. fpp - Fortran PreProcessor + Copyright (C) 2002-2020 Intel Corporation. All rights reserved. + +Portions Copyright (C) 1995 by Sun Microsystems, Inc. +All rights reserved. + +Developed at SunSoft, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + +----------------------------------------------------------------- + +5. Intel compute-runtime + Copyright 2019 Intel Corporation. + + Intel vc-intrinsics + Copyright 2021 Intel Corporation. + + libffi + Copyright (c) 1996-2021 Anthony Green, Red Hat, Inc and others. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +----------------------------------------------------------------- + +6. protobuf + Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. +----------------------------------------------------------------- + +7. MP11 + Copyright 2021 Intel Corporation. + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +----------------------------------------------------------------- + +8. Unicode Data Files +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +See Terms of Use <https://www.unicode.org/copyright.html> +for definitions of Unicode Inc.’s Data Files and Software. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2022 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +----------------------------------------------------------------- +The following third party programs have their own third party program files. +These additional third party program files can be found as follows: +1. Threading Building Blocks: +<install_dir>/tbb/licensing/third-party-programs.txt + +----------------------------------------------------------------- + +Intel(R) 2021.8 C/C++/Fortran Compiler Classic Third Party Programs File + +This file is the "third-party-programs.txt" file specified in the associated Intel end user license agreement for the Intel software you are licensing. + +Third party programs and their corresponding required notices and/or license terms are listed below. + +----------------------------------------------------------------- + +1. libdwarf +Copyright 2020 Intel Corporatio + +LIBDWARF Copyright To enable use of the DWARF2 libdwarf interface, the following copyright and notice must be included in this document. Note this notice is for libdwarf only. All other source and documentation are copyright by Intel Corp. LIBDWARF permission notice: Copyright (c) 1994 Silicon Graphics, Inc. Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that (i) the above copyright notice and this permission notice appear in all copies of the software and related documentation, and (ii) the name "Silicon Graphics" or any other trademark of Silicon Graphics, Inc. may not be used in any advertising or publicity relating to the software without the specific, prior written permission of Silicon Graphics, Inc. THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +----------------------------------------------------------------- + + +2. Alladin Enterprises MD5 + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. + +All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com + +----------------------------------------------------------------- + +3. ATL Server Library and Tools + +Microsoft Limited Permissive License (Ms-LPL) +Published: October 18, 2005 +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. +1. Definitions + o The terms "reproduce," "reproduction" and "distribution" have the same meaning here as under U.S. copyright law. + o "You" means the licensee of the software. + o "Licensed patents" means any Microsoft patent claims which read directly on the software as distributed by Microsoft under this license. + +2. Grant of Rights + a. Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, Microsoft grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce the software, prepare derivative works of the software and distribute the software or any derivative works that you create. + b. Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, Microsoft grants you a non-exclusive, worldwide, royalty-free patent license under licensed patents to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the software or derivative works of the software. + +3. Conditions and Limitations + . No Trademark License- This license does not grant you any rights to use Microsoft's name, logo, or trademarks. + a. If you begin patent litigation against Microsoft over patents that you think may apply to the software (including a cross-claim or counterclaim in a lawsuit), your license to the software ends automatically. + b. If you distribute copies of the software or derivative works, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + c. If you distribute the software or derivative works in source code form you may do so only under this license (i.e., you must include a complete copy of this license with your distribution), and if you distribute the software or derivative works in compiled or object code form you may only do so under a license that complies with this license. + d. The software is licensed "as-is." You bear the risk of using it. Microsoft gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, Microsoft excludes the implied warranties of merchantability, fitness for a particular purpose and non-infringement. + e. Platform Limitation- The licenses granted in sections 2(A) & 2(B) extend only to the software or derivative works that you create that run on a Microsoft Windows operating system product. + +----------------------------------------------------------------- + +5. llvm-project llvm-project + Copyright 2020 Intel Corporation + + Intel Open Source Compiler Header Files + Copyright 2020 Intel Corporation + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + "License" shall mean the terms and conditions for use, reproduction and distribution as defined by Sections 1 through 9 of this document. + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + "Source" form shall mean the preferred form for making modifications including but not limited to software source code, documentation source, and configuration files. +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems,and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of,publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain + to any part of the Derivative Works; and + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those + notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if + provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes + only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional + attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and condition for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in + writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility + of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations + and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to + indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + APPENDIX: How to apply the Apache License to your work. + To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be + enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and limitations under the License. + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. + +----------------------------------------------------------------- + +6. Intel® Threading Building Blocks (Intel® TBB) + Copyright Intel Corporation + + + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +----------------------------------------------------------------- + +7. Visual Studio Autogenerated Code + Copyright Microsoft Corporation + +Terms for Microsoft “Distributable Code” provided as part of Microsoft’s Visual Studio Enterprise and Professional software. + +1. License. This software package from Intel (the “Software Package”) contains code from Microsoft (the “Distributable Code”). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code. +2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: +• work around any technical limitations in the Distributable Code; +• reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; +• remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; +• use the Distributable Code in any way that is against the law; or +• share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. +3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS” WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. +4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. +This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. +5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. + +----------------------------------------------------------------- + +8. fpp - Fortran PreProcessor + Copyright (C) 2002-2018 Intel Corporation. All rights reserved. + +Portions Copyright (C) 1995 by Sun Microsystems, Inc. +All rights reserved. + +Developed at SunSoft, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + +----------------------------------------------------------------- +9. Intel Decimal Floating-Point Math Library +Copyright (c) 2018, Intel Corp. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + his list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +----------------------------------------------------------------- +The following third party programs have their own third party program files. These additional third party program files are as follows: + + Third-party-program.txt file for Intel(R) TBB is located here: + <install_dir>/tbb/licensing/third-party-programs.txt + +------------------------------------------------------------- +Other names and brands may be claimed as the property of others. + + diff --git a/third-party-programs-oneDNN.txt b/third-party-programs-oneDNN.txt new file mode 100644 index 00000000..1b8bbccb --- /dev/null +++ b/third-party-programs-oneDNN.txt @@ -0,0 +1,583 @@ +oneAPI Deep Neural Network Library (oneDNN) Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license +terms. This third party software, even if included with the distribution of +the Intel software, may be governed by separate license terms, including +without limitation, third party license terms, other Intel software license +terms, and open source software license terms. These separate license terms +govern your use of the third party programs as set forth in in the +"THIRD-PARTY-PROGRAMS" file. + +Third party programs and their corresponding required notices and/or license +terms are listed below. + +-------------------------------------------------------------------------------- +1. XByak (src/cpu/xbyak/) +Copyright (c) 2007 MITSUNARI Shigeo +All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of the copyright owner nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + + +ソースコード形å¼ã‹ãƒã‚¤ãƒŠãƒªå½¢å¼ã‹ã€å¤‰æ›´ã™ã‚‹ã‹ã—ãªã„ã‹ã‚’å•ã‚ãšã€ä»¥ä¸‹ã®æ¡ä»¶ã‚’満㟠+ã™å ´åˆã«é™ã‚Šã€å†é ’布ãŠã‚ˆã³ä½¿ç”¨ãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚ + +ソースコードをå†é ’布ã™ã‚‹å ´åˆã€ä¸Šè¨˜ã®è‘—作権表示ã€æœ¬æ¡ä»¶ä¸€è¦§ã€ãŠã‚ˆã³ä¸‹è¨˜å…責æ¡é … +ã‚’å«ã‚ã‚‹ã“ã¨ã€‚ +ãƒã‚¤ãƒŠãƒªå½¢å¼ã§å†é ’布ã™ã‚‹å ´åˆã€é ’布物ã«ä»˜å±žã®ãƒ‰ã‚ュメントç‰ã®è³‡æ–™ã«ã€ä¸Šè¨˜ã®è‘—作 +権表示ã€æœ¬æ¡ä»¶ä¸€è¦§ã€ãŠã‚ˆã³ä¸‹è¨˜å…責æ¡é …ã‚’å«ã‚ã‚‹ã“ã¨ã€‚ +書é¢ã«ã‚ˆã‚‹ç‰¹åˆ¥ã®è¨±å¯ãªã—ã«ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‹ã‚‰æ´¾ç”Ÿã—ãŸè£½å“ã®å®£ä¼ã¾ãŸã¯è²©å£²ä¿ƒé€² +ã«ã€è‘—作権者ã®åå‰ã¾ãŸã¯ã‚³ãƒ³ãƒˆãƒªãƒ“ューターã®åå‰ã‚’使用ã—ã¦ã¯ãªã‚‰ãªã„。 +本ソフトウェアã¯ã€è‘—作権者ãŠã‚ˆã³ã‚³ãƒ³ãƒˆãƒªãƒ“ューターã«ã‚ˆã£ã¦ã€Œç¾çŠ¶ã®ã¾ã¾ã€æ供㕠+ã‚Œã¦ãŠã‚Šã€æ˜Žç¤ºé»™ç¤ºã‚’å•ã‚ãšã€å•†æ¥çš„ãªä½¿ç”¨å¯èƒ½æ€§ã€ãŠã‚ˆã³ç‰¹å®šã®ç›®çš„ã«å¯¾ã™ã‚‹é©åˆæ€§ +ã«é–¢ã™ã‚‹æš—é»™ã®ä¿è¨¼ã‚‚å«ã‚ã€ã¾ãŸãã‚Œã«é™å®šã•ã‚Œãªã„ã€ã„ã‹ãªã‚‹ä¿è¨¼ã‚‚ã‚ã‚Šã¾ã›ã‚“。 +著作権者もコントリビューターもã€äº‹ç”±ã®ã„ã‹ã‚“ã‚’å•ã‚ãšã€ æ害発生ã®åŽŸå› ã„ã‹ã‚“ã‚’ +å•ã‚ãšã€ã‹ã¤è²¬ä»»ã®æ ¹æ‹ ãŒå¥‘ç´„ã§ã‚ã‚‹ã‹åŽ³æ ¼è²¬ä»»ã§ã‚ã‚‹ã‹ï¼ˆéŽå¤±ãã®ä»–ã®ï¼‰ä¸æ³•è¡Œç‚ºã§ +ã‚ã‚‹ã‹ã‚’å•ã‚ãšã€ä»®ã«ãã®ã‚ˆã†ãªæ害ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ã‚’知らã•ã‚Œã¦ã„ãŸã¨ã—ã¦ã‚‚〠+本ソフトウェアã®ä½¿ç”¨ã«ã‚ˆã£ã¦ç™ºç”Ÿã—ãŸï¼ˆä»£æ›¿å“ã¾ãŸã¯ä»£ç”¨ã‚µãƒ¼ãƒ“スã®èª¿é”ã€ä½¿ç”¨ã® +喪失ã€ãƒ‡ãƒ¼ã‚¿ã®å–ªå¤±ã€åˆ©ç›Šã®å–ªå¤±ã€æ¥å‹™ã®ä¸æ–ã‚‚å«ã‚ã€ã¾ãŸãã‚Œã«é™å®šã•ã‚Œãªã„)直接 +æ害ã€é–“接æ害ã€å¶ç™ºçš„ãªæ害ã€ç‰¹åˆ¥æ害ã€æ‡²ç½°çš„æ害ã€ã¾ãŸã¯çµæžœæ害ã«ã¤ã„ã¦ã€ +ä¸€åˆ‡è²¬ä»»ã‚’è² ã‚ãªã„ã‚‚ã®ã¨ã—ã¾ã™ã€‚ + +-------------------------------------------------------------------------------- +2. Googletest (tests/gtests/gtest/) +Copyright 2005, Google Inc. +Copyright 2006, Google Inc. +Copyright 2007, Google Inc. +Copyright 2008, Google Inc. +Copyright 2015, Google Inc. +All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- +3. Instrumentation and Tracing Technology API (src/common/ittnotify/) +Copyright (c) 2011, Intel Corporation. All rights reserved. +Copyright (c) 2005-2014 Intel Corporation. All rights reserved. + +3-Clause BSD License + +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. + +3. Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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. + +-------------------------------------------------------------------------------- +4. CMake (cmake/FindOpenCL.cmake, cmake/FindBLAS.cmake, cmake/FindACL.cmake) +CMake - Cross Platform Makefile Generator +Copyright 2000-2020 Kitware, Inc. and Contributors +All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Kitware, Inc. nor the names of Contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +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. + +------------------------------------------------------------------------------ + +The following individuals and institutions are among the Contributors: + +* Aaron C. Meadows <cmake@shadowguarddev.com> +* Adriaan de Groot <groot@kde.org> +* Aleksey Avdeev <solo@altlinux.ru> +* Alexander Neundorf <neundorf@kde.org> +* Alexander Smorkalov <alexander.smorkalov@itseez.com> +* Alexey Sokolov <sokolov@google.com> +* Alex Merry <alex.merry@kde.org> +* Alex Turbov <i.zaufi@gmail.com> +* Andreas Pakulat <apaku@gmx.de> +* Andreas Schneider <asn@cryptomilk.org> +* André Rigland Brodtkorb <Andre.Brodtkorb@ifi.uio.no> +* Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf +* Benjamin Eikel +* Bjoern Ricks <bjoern.ricks@gmail.com> +* Brad Hards <bradh@kde.org> +* Christopher Harvey +* Christoph Grüninger <foss@grueninger.de> +* Clement Creusot <creusot@cs.york.ac.uk> +* Daniel Blezek <blezek@gmail.com> +* Daniel Pfeifer <daniel@pfeifer-mail.de> +* Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> +* Eran Ifrah <eran.ifrah@gmail.com> +* Esben Mose Hansen, Ange Optimization ApS +* Geoffrey Viola <geoffrey.viola@asirobots.com> +* Google Inc +* Gregor Jasny +* Helio Chissini de Castro <helio@kde.org> +* Ilya Lavrenov <ilya.lavrenov@itseez.com> +* Insight Software Consortium <insightsoftwareconsortium.org> +* Jan Woetzel +* Julien Schueller +* Kelly Thompson <kgt@lanl.gov> +* Konstantin Podsvirov <konstantin@podsvirov.pro> +* Laurent Montel <montel@kde.org> +* Mario Bensi <mbensi@ipsquad.net> +* Martin Gräßlin <mgraesslin@kde.org> +* Mathieu Malaterre <mathieu.malaterre@gmail.com> +* Matthaeus G. Chajdas +* Matthias Kretz <kretz@kde.org> +* Matthias Maennich <matthias@maennich.net> +* Michael Hirsch, Ph.D. <www.scivision.co> +* Michael Stürmer +* Miguel A. Figueroa-Villanueva +* Mike Jackson +* Mike McQuaid <mike@mikemcquaid.com> +* Nicolas Bock <nicolasbock@gmail.com> +* Nicolas Despres <nicolas.despres@gmail.com> +* Nikita Krupen'ko <krnekit@gmail.com> +* NVIDIA Corporation <www.nvidia.com> +* OpenGamma Ltd. <opengamma.com> +* Patrick Stotko <stotko@cs.uni-bonn.de> +* Per Øyvind Karlsen <peroyvind@mandriva.org> +* Peter Collingbourne <peter@pcc.me.uk> +* Petr Gotthard <gotthard@honeywell.com> +* Philip Lowman <philip@yhbt.com> +* Philippe Proulx <pproulx@efficios.com> +* Raffi Enficiaud, Max Planck Society +* Raumfeld <raumfeld.com> +* Roger Leigh <rleigh@codelibre.net> +* Rolf Eike Beer <eike@sf-mail.de> +* Roman Donchenko <roman.donchenko@itseez.com> +* Roman Kharitonov <roman.kharitonov@itseez.com> +* Ruslan Baratov +* Sebastian Holtermann <sebholt@xwmw.org> +* Stephen Kelly <steveire@gmail.com> +* Sylvain Joubert <joubert.sy@gmail.com> +* The Qt Company Ltd. +* Thomas Sondergaard <ts@medical-insight.com> +* Tobias Hunger <tobias.hunger@qt.io> +* Todd Gamblin <tgamblin@llnl.gov> +* Tristan Carel +* University of Dundee +* Vadim Zhukov +* Will Dicharry <wdicharry@stellarscience.com> + +See version control history for details of individual contributions. + +The above copyright and license notice applies to distributions of +CMake in source and binary form. Third-party software packages supplied +with CMake under compatible licenses provide their own copyright notices +documented in corresponding subdirectories or source files. + +------------------------------------------------------------------------------ + +CMake was initially developed by Kitware with the following sponsorship: + + * National Library of Medicine at the National Institutes of Health + as part of the Insight Segmentation and Registration Toolkit (ITK). + + * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel + Visualization Initiative. + + * National Alliance for Medical Image Computing (NAMIC) is funded by the + National Institutes of Health through the NIH Roadmap for Medical Research, + Grant U54 EB005149. + + * Kitware, Inc. + +-------------------------------------------------------------------------------- +5. Xbyak_aarch64 (src/cpu/aarch64/xbyak_aarch64/) +Copyright 2019-2020 FUJITSU LIMITED + +Apache License, Version 2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +-------------------------------------------------------------------------------- +6. Boost C++ Libraries (src/common/primitive_hashing.hpp) +Copyright 2005-2014 Daniel James. + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- +7. Intel(R) Graphics Compute Runtime for oneAPI Level Zero and OpenCL(TM) +Driver (src/gpu/jit/ngen/npack/{elf_structs,hash}.hpp) +Copyright (c) 2018 Intel Corporation + +Intel(R) Graphics Compiler (src/gpu/jit/ngen/npack/neo_structs.hpp) +Copyright (c) 2019 Intel Corporation + +oneAPI Level Zero (src/sycl/level_zero) +Copyright (C) 2019-2021 Intel Corporation + +Doxyrest toolkit (doc/doxyrest/*) +Copyright (c) 2016, Tibbo Technology Inc +Copyright (c) 2016, Vladimir Gladkov +Copyright (c) 2016, Doxyrest maintainers + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +8. Sphinx (doc/sphinx/conf/py) +Copyright (c) 2007-2021 by the Sphinx team (see AUTHORS file). +All rights reserved. + +2-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +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. +-------------------------------------------------------------------------------- +9. Intel(R) Metrics Discovery Application Programming Interface (src/gpu/ocl/mdapi/metrics_discovery_api.h) +MIT License + +Copyright (c) 2019, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/third-party-programs-oneTBB.txt b/third-party-programs-oneTBB.txt new file mode 100644 index 00000000..b555450a --- /dev/null +++ b/third-party-programs-oneTBB.txt @@ -0,0 +1,411 @@ +oneAPI Threading Building Blocks (oneTBB) Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license terms. +This third party software, even if included with the distribution of the Intel +software, may be governed by separate license terms, including without limitation, +third party license terms, other Intel software license terms, and open source +software license terms. These separate license terms govern your use of the third +party programs as set forth in the "third-party-programs.txt" or other similarlynamed text file. + +The third party programs and their corresponding required notices and/or license +terms are listed below. +_______________________________________________________________________________________________________ + +1. Intel(R) Instrumentation and Tracing Technology (ITT) + Copyright (c) 2022 Intel Corporation. All rights reserved. + + 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. + 3. Neither the name of the copyright holder nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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. + +_______________________________________________________________________________________________________ + +2. ActiveState Thread pool with same API as (multi) processing.Pool (Python recipe): + Copyright (c) 2008,2016 david decotigny (this file) + Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool) + + Portable Hardware Locality (hwloc) + Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana University Research and Technology Corporation. All rights reserved. + Copyright (c) 2004-2005 The University of Tennessee and The University of Tennessee Research Foundation. All rights reserved. + Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, University of Stuttgart. All rights reserved. + Copyright (c) 2004-2005 The Regents of the University of California. All rights reserved. + Copyright (c) 2009 CNRS + Copyright (c) 2009-2016 Inria. All rights reserved. + Copyright (c) 2009-2015 Université Bordeaux + Copyright (c) 2009-2015 Cisco Systems, Inc. All rights reserved. + Copyright (c) 2009-2012 Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2010 IBM + Copyright (c) 2010 Jirka Hladky + Copyright (c) 2012 Aleksej Saushev, The NetBSD Foundation + Copyright (c) 2012 Blue Brain Project, EPFL. All rights reserved. + Copyright (c) 2013-2014 University of Wisconsin-La Crosse. All rights reserved. + Copyright (c) 2015 Research Organization for Information Science and Technology (RIST). All rights reserved. + Copyright (c) 2015-2016 Intel, Inc. All rights reserved. + + BSD 3-clause "New" or "Revised" License + + 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. + 3. Neither the name of author nor the names of any contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +_______________________________________________________________________________________________________ + +3. gperftools: Copyright (c) 2011, Google Inc. + + Tachyon: Copyright (c) 1994-2008 John E. Stone. All rights reserved. + + BSD 3-Clause "New" or "Revised" License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +_______________________________________________________________________________________________________ + +4. Mateusz Kwiatkowski Workaround for bug 62258 in libstdc++ + + GPL 3.0 with GCC Runtime Library Exception 3.1 + + GNU GENERAL PUBLIC LICENSE + + Version 3, 29 June 2007 + + Copyright (c) 2007 Free Software Foundation, Inc. <https://fsf.org/> + + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + + Preamble + The GNU General Public License is a free, copyleft license for software and other kinds of works. + + The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + + When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + + Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + + Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and modification follow. + + TERMS AND CONDITIONS + 0. Definitions. + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based on the Program. + + To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + + 1. Source Code. + The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. + + A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + + The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + + The Corresponding Source for a work in source code form is that same work. + + 2. Basic Permissions. + All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + + When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + + 4. Conveying Verbatim Copies. + You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + + 6. Conveying Non-Source Forms. + You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + + If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + + The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + + 7. Additional Terms. + "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + + 8. Termination. + You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + + However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + + Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + + 9. Acceptance Not Required for Having Copies. + You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + + 11. Patents. + A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + + If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + + A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + + 14. Revised Versions of this License. + The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + + Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + + 15. Disclaimer of Warranty. + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/licenses/why-not-lgpl.html>. + + + GCC RUNTIME LIBRARY EXCEPTION + + Version 3.1, 31 March 2009 + + Copyright (c) 2009 Free Software Foundation, Inc. <https://fsf.org/> + + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + + This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception. + + When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception. + + 0. Definitions. + A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library. + + "GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF. + + "GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC. + + "Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation. + + The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors. + + A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process. + + 1. Grant of Additional Permission. + You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules. + + 2. No Weakening of GCC Copyleft. + The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. + +_______________________________________________________________________________________________________ + +5. Doctest + + Copyright (c) 2016-2021 Viktor Kirilov + + The MIT License (MIT) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +_______________________________________________________________________________________________________ + +*Other names and brands may be claimed as the property of others. diff --git a/third-party-programs.txt b/third-party-programs.txt index 89c256ea..8a6ab642 100644 --- a/third-party-programs.txt +++ b/third-party-programs.txt @@ -1,15 +1,12 @@ Intel(R) OSPRay Studio Third Party Programs File - This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "third-party-programs.txt" or other similarly- named text file. - Third party programs andjk their corresponding required notices and/or license terms are listed below. -------------------------------------------------------------------------------- 1. Google Benchmark Copyright 2018 Google Inc. All rights reserved. Intel(R) OSPRay - Copyright 2009 Intel Corporation - + Copyright 2009-2020 Intel Corporation Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ @@ -439,25 +436,25 @@ Library. 6. Visual C++ Redistributables for Visual Studio Copyright Microsoft Corp. -Terms for Microsoft “Distributable Code” provided as part of Microsoft’s Visual Studio Enterprise and Professional software. -1. License. This software package from Intel (the “Software Package”) contains code from Microsoft (the “Distributable Code”). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code. +1. License. This software package from Intel (the “Software Packageâ€) contains code from Microsoft (the “Distributable Codeâ€). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use and redistribute the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code on a stand-alone basis. 2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: -• work around any technical limitations in the Distributable Code; -• reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; -• remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; -• use the Distributable Code in any way that is against the law; or -• share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. -3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS” WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. +• work around any technical limitations in the Distributable Code; +• reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; +• remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; +• use the Distributable Code in any way that is against the law; or +• share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. +3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS†WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. 4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. 5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. + -------------------------------------------------------------------------------- 7. Dear ImGui Copyright 2014-2020 Omar Cornut Dirent - Copyright (c) 2015 Toni Rönkkö + Copyright (c) 2015 Toni Rönkkö ImGuiFileDialog Copyright (c) 2018-2020 Stephane Cuillerdier (aka Aiekick) @@ -468,25 +465,25 @@ This limitation applies to (a) anything related to the Distributable Code; and ( Nothings STB Image (Nothings STB libraries) Copyright (c) 2017 Sean Barrett + tinydng + Copyright (c) 2016-Present Syoyo Fujita and many contributors. + tinygltf - Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors + Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors tinyobjloader Copyright (c) 2012-2019 Syoyo Fujita and many contributors. - The MIT License (MIT) - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------------------- 8. GLFW Copyright 2002-2006 Marcus Geelnard - Copyright 2006-2019 Camilla Löwy + Copyright 2006-2019 Camilla Löwy This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -531,10 +528,367 @@ Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing external contributions to this project including patches, pull requests, etc. -------------------------------------------------------------------------------- -The following third party programs have their own third party programs. These additional third party program files are as follows: +10. Draco -1. OSPRay: ./third-party-programs-OSPRay.txt + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- +Files: docs/assets/js/ASCIIMathML.js + +Copyright (c) 2014 Peter Jipsen and other ASCIIMathML.js contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -Other names and brands may be claimed as the property of others. +Files: docs/assets/css/pygments/* + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org> + + +-------------------------------------------------------------------------------- +11.Tiny OpenEXR + +/* +Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Syoyo Fujita nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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. +*/ + +// TinyEXR contains some OpenEXR code, which is licensed under ------------ + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +// End of OpenEXR license ------------------------------------------------- + +-------------------------------------------------------------------------------- +12. Point Cloud Library (PCL) - www.pointclouds.org + Copyright (c) 2009-2012, Willow Garage, Inc. + Copyright (c) 2012-, Open Perception, Inc. + Copyright (c) XXX, respective authors. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the copyright holder(s) nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +The following third party programs have their own third party programs. These additional third party program files are as follows: +1. OSPRay: ./third-party-programs-OSPRay.txt