From 821a95ff569024b52221bb24fd00a52f871b5d12 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 Feb 2025 21:06:26 +0100 Subject: [PATCH] Stb (#3823) * Move STB internally, comment functions if not Signed-off-by: Omar Shrit * Comment for now STB including macros Signed-off-by: Omar Shrit * Modify CMake and tests accordingly Signed-off-by: Omar Shrit * Fix the license and update the date. Signed-off-by: Omar Shrit * Move STB to its own directory Signed-off-by: Omar Shrit * Adding the functrions of image resize and crop Signed-off-by: Omar Shrit * Update the API not finished yet Signed-off-by: Omar Shrit * Start adding tests Signed-off-by: Omar Shrit * Add flowers images for test Signed-off-by: Omar Shrit * Bring image from the coco dataset Signed-off-by: Omar Shrit * Include all of STB header in this file Signed-off-by: Omar Shrit * Fix STB configs Signed-off-by: Omar Shrit * Clean CMakeLists and look for stb_resize Signed-off-by: Omar Shrit * Make it compile with STB integrated Signed-off-by: Omar Shrit * Fix stb path Signed-off-by: Omar Shrit * Fix the endif at the end of the file Signed-off-by: Omar Shrit * Update LICENSE.txt Co-authored-by: Ryan Curtin * Update CMakeLists.txt Co-authored-by: Ryan Curtin * Update src/mlpack/config.hpp Co-authored-by: Ryan Curtin * Adding the function and test, not finished Signed-off-by: Omar Shrit * Remove crop from this PR, and add tests Signed-off-by: Omar Shrit * Update LICENSE.txt Co-authored-by: Dirk Eddelbuettel * Update CMakeLists.txt Co-authored-by: Dirk Eddelbuettel * merge master Signed-off-by: Omar Shrit * Add @rcutin suggestion for stb Signed-off-by: Omar Shrit * Improve the logic to include edge cases Signed-off-by: Omar Shrit * Fix the bundle that if we are using system stb Signed-off-by: Omar Shrit * Make it possible to disable the entire build with STB Signed-off-by: Omar Shrit * Fix the else if condition Signed-off-by: Omar Shrit * Fix the else condition Signed-off-by: Omar Shrit * Fix the tests accordindly Signed-off-by: Omar Shrit * Add dummpy functions and complete the Resize function Signed-off-by: Omar Shrit * Reorder to see if this fix the problem Signed-off-by: Omar Shrit * Fix the resize for a set of images Signed-off-by: Omar Shrit * Add STATIC for resize and write Signed-off-by: Omar Shrit * Fix all the problem with this function Signed-off-by: Omar Shrit * Be able to resize N images easily Signed-off-by: Omar Shrit * Add the tests, already passing Signed-off-by: Omar Shrit * Use sheep instead of Umbrella Signed-off-by: Omar Shrit * Fix STB directory Signed-off-by: Omar Shrit * Fix Cmake and docs Signed-off-by: Omar Shrit * Apply comments from @rcurtin Signed-off-by: Omar Shrit * Integrate @rcurtin comments Signed-off-by: Omar Shrit * Fix tests and remove generated images Signed-off-by: Omar Shrit * Add docs Signed-off-by: Omar Shrit * Update the API with new resize version Signed-off-by: Omar Shrit * Fix to resize2 Signed-off-by: Omar Shrit * Adding resize2 Signed-off-by: Omar Shrit * Add the necessary fix to avoid linker errors Signed-off-by: Omar Shrit * Add configs to allow correct repacking Signed-off-by: Omar Shrit * Redo the ResizeImages function Signed-off-by: Omar Shrit * Pack the images as tzr.bz2 Signed-off-by: Omar Shrit * Fix the function calls and create an internal one Signed-off-by: Omar Shrit * Make the message shorter to have under 80 chars Signed-off-by: Omar Shrit * Solve linter errors Signed-off-by: Omar Shrit * Solve linter error Signed-off-by: Omar Shrit * Fix linter issues Signed-off-by: Omar Shrit * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update src/mlpack/tests/image_test.cpp Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update src/mlpack/tests/image_test.cpp Co-authored-by: Ryan Curtin * Update src/mlpack/tests/image_test.cpp Co-authored-by: Ryan Curtin * Update src/mlpack/tests/image_test.cpp Co-authored-by: Ryan Curtin * Update src/mlpack/tests/image_test.cpp Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Apply @rcurtin comments Signed-off-by: Omar Shrit * Add an example usage of these two functions Signed-off-by: Omar Shrit * Apply @rcurtin comments Signed-off-by: Omar Shrit * Re-organize directories for STB Signed-off-by: Omar Shrit * Apply rcurtin comments Signed-off-by: Omar Shrit * Merge two resize functions into one Signed-off-by: Omar Shrit * Get rid of MLPACK_DISABLE_STB Signed-off-by: Omar Shrit * Fix forgetting docs Signed-off-by: Omar Shrit * Update CMake/FindStbImage.cmake Co-authored-by: Ryan Curtin * Update CMake/FindStbImage.cmake Co-authored-by: Ryan Curtin * Update doc/user/install.md Co-authored-by: Ryan Curtin * Update doc/user/compile.md Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Update src/mlpack/core/data/image_resize_crop.hpp Co-authored-by: Ryan Curtin * Update doc/user/load_save.md Co-authored-by: Ryan Curtin * Apply comments from @rcurtin Signed-off-by: Omar Shrit * Adding the test to test if it is identical Signed-off-by: Omar Shrit * Fix image tests Signed-off-by: Omar Shrit * Fix the example Signed-off-by: Omar Shrit * Add the link and the patch to download the images Signed-off-by: Omar Shrit * Fix the script and make all of them green Signed-off-by: Omar Shrit * Remove wget not needed Signed-off-by: Omar Shrit * Minor style fixes. * Avoid temporary matrices, and test with multiple different types. * Update src/mlpack/config.hpp Co-authored-by: Ryan Curtin * Update HISTORY.md Co-authored-by: Ryan Curtin * Fix R build by including bundled STB headers in package. --------- Signed-off-by: Omar Shrit Signed-off-by: Omar Shrit Co-authored-by: Ryan Curtin Co-authored-by: Dirk Eddelbuettel --- CMake/FindStbImage.cmake | 4 +- CMakeLists.txt | 32 +- HISTORY.md | 2 + LICENSE.txt | 10 +- doc/user/compile.md | 5 +- doc/user/install.md | 1 + doc/user/load_save.md | 86 + scripts/test-docs.sh | 14 +- src/mlpack/bindings/R/CMakeLists.txt | 3 +- src/mlpack/config.hpp | 60 +- src/mlpack/core.hpp | 1 + src/mlpack/core/data/data.hpp | 1 + src/mlpack/core/data/image_info_impl.hpp | 4 - src/mlpack/core/data/image_resize_crop.hpp | 135 + src/mlpack/core/data/load_image.hpp | 28 +- src/mlpack/core/data/load_image_impl.hpp | 25 - src/mlpack/core/data/save_image.hpp | 26 +- src/mlpack/core/data/save_image_impl.hpp | 25 - src/mlpack/core/stb/bundled/stb_image.h | 7988 ++++++++++++ .../core/stb/bundled/stb_image_resize2.h | 10601 ++++++++++++++++ src/mlpack/core/stb/bundled/stb_image_write.h | 1724 +++ src/mlpack/core/stb/stb.hpp | 85 + src/mlpack/tests/CMakeLists.txt | 3 +- src/mlpack/tests/data/sheep.tar.bz2 | Bin 0 -> 668234 bytes .../{image_load_test.cpp => image_test.cpp} | 91 +- .../tests/main_tests/image_converter_test.cpp | 4 - 26 files changed, 20762 insertions(+), 196 deletions(-) create mode 100644 src/mlpack/core/data/image_resize_crop.hpp create mode 100644 src/mlpack/core/stb/bundled/stb_image.h create mode 100644 src/mlpack/core/stb/bundled/stb_image_resize2.h create mode 100644 src/mlpack/core/stb/bundled/stb_image_write.h create mode 100644 src/mlpack/core/stb/stb.hpp create mode 100644 src/mlpack/tests/data/sheep.tar.bz2 rename src/mlpack/tests/{image_load_test.cpp => image_test.cpp} (61%) diff --git a/CMake/FindStbImage.cmake b/CMake/FindStbImage.cmake index ae2898eeec..e0917228f0 100644 --- a/CMake/FindStbImage.cmake +++ b/CMake/FindStbImage.cmake @@ -12,7 +12,7 @@ file(GLOB STB_IMAGE_SEARCH_PATHS ${CMAKE_BINARY_DIR}/deps/ ${CMAKE_BINARY_DIR}/deps/stb) find_path(STB_IMAGE_INCLUDE_DIR_1 - NAMES stb_image.h stb_image_write.h + NAMES stb_image.h stb_image_write.h stb_image_resize2.h PATHS ${STB_IMAGE_SEARCH_PATHS} ${STB_IMAGE_INCLUDE_DIR}) if(STB_IMAGE_INCLUDE_DIR_1) @@ -26,7 +26,7 @@ if(STB_IMAGE_INCLUDE_DIR_1) set(STB_INCLUDE_NEEDS_STB_SUFFIX "NO") else () find_path(STB_IMAGE_INCLUDE_DIR_2 - NAMES stb_image.h stb_image_write.h + NAMES stb_image.h stb_image_write.h stb_image_resize2.h PATHS ${STB_IMAGE_SEARCH_PATHS} ${STB_IMAGE_INCLUDE_DIR} PATH_SUFFIXES stb/) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06b2ebf2f2..ebf4c5164f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON) option(DOWNLOAD_DEPENDENCIES "Automatically download dependencies if not available." OFF) option(BUILD_GO_SHLIB "Build Go shared library." OFF) option(USE_PRECOMPILED_HEADERS "Use precompiled headers for mlpack_test build." ON) +option(USE_SYSTEM_STB "Use system STB instead of version bundled with mlpack." OFF) # Set minimum library versions required by mlpack. # @@ -314,20 +315,12 @@ endif() set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS}) set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${ARMADILLO_LIBRARIES}) -# Find stb_image.h and stb_image_write.h. -if (NOT DOWNLOAD_DEPENDENCIES) - find_package(StbImage) -else() - find_package(StbImage) - if (NOT StbImage_FOUND) - get_deps(https://mlpack.org/files/stb.tar.gz stb stb.tar.gz) - set(STB_IMAGE_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) - find_package(StbImage REQUIRED) - endif() +if (USE_SYSTEM_STB) + find_package(StbImage REQUIRED) endif() - if (StbImage_FOUND) set(STB_AVAILABLE "1") + add_definitions(-DMLPACK_USE_SYSTEM_STB) set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${STB_IMAGE_INCLUDE_DIR}") # Make sure that we can link STB in multiple translation units. @@ -337,7 +330,7 @@ if (StbImage_FOUND) "multiple translation units! Try upgrading your STB implementation, " "or using the auto-downloader (set DOWNLOAD_DEPENDENCIES=ON in the " "CMake configuration command.") - endif () + endif() endif() # Find ensmallen. @@ -483,18 +476,17 @@ if (BFD_DL_AVAILABLE) string(REGEX REPLACE "// #define MLPACK_HAS_BFD_DL\n" "#define MLPACK_HAS_BFD_DL\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}") endif () -if (STB_AVAILABLE) - string(REGEX REPLACE "// #define MLPACK_HAS_STB\n" - "#define MLPACK_HAS_STB\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}") - if (NOT STB_INCLUDE_NEEDS_STB_SUFFIX) - string(REGEX REPLACE "// #define MLPACK_HAS_NO_STB_DIR\n" - "#define MLPACK_HAS_NO_STB_DIR\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}") - endif () -endif () + if (USING_GIT) string(REGEX REPLACE "// #define MLPACK_GIT_VERSION\n" "#define MLPACK_GIT_VERSION\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}") endif () + +if (USE_SYSTEM_STB) + string(REGEX REPLACE "// #define MLPACK_USE_SYSTEM_STB\n" + "#define MLPACK_USE_SYSTEM_STB\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}") +endif() + file(WRITE ${CMAKE_BINARY_DIR}/include/mlpack/config-local.hpp "${CONFIG_CONTENTS}") include_directories(${CMAKE_BINARY_DIR}/include/) add_definitions(-DMLPACK_CUSTOM_CONFIG_FILE=mlpack/config-local.hpp) diff --git a/HISTORY.md b/HISTORY.md index a3ae7c13de..34b3ead87c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,8 @@ _????-??-??_ * Add `MLPACK_NO_STD_MUTEX` to allow disabling `std::mutex` (#3868). + * Bundle STB with mlpack and add `ResizeImages()` functionality (#3823). + ## mlpack 4.5.1 _2024-12-02_ diff --git a/LICENSE.txt b/LICENSE.txt index cb1cee1aec..ade292fa18 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -3,7 +3,7 @@ can redistribute the library and/or modify it under the terms of the 3-clause BSD license. The text of the 3-clause BSD license is contained below. ---- -Copyright (c) 2007-2023, mlpack contributors (see COPYRIGHT.txt) +Copyright (c) 2007-2025, mlpack contributors (see COPYRIGHT.txt) All rights reserved. Redistribution and use of mlpack in source and binary forms, with or without @@ -32,7 +32,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------ -mlpack also contains some usage of the source code of MNMLSTC Core library, -which is a backport of C++17 features to C++11. MNMLSTC is licensed under the -Apache 2.0 License. This code can be found in src/mlpack/core/std_backport/ and -more details about licensing can be found there. +mlpack also contains some usage of the source code of the STB library, +which is providing support for image loading, saving and resizing. STB is +dual-licensed under the MIT license and the public domain. This code can be +found in src/mlpack/core/stb/ for more details about licensing and usage. diff --git a/doc/user/compile.md b/doc/user/compile.md index c29fc03185..f6ac27be22 100644 --- a/doc/user/compile.md +++ b/doc/user/compile.md @@ -61,8 +61,11 @@ program (before including mlpack or Armadillo!). |---------------------------|-------------------|---------------| |*Functionality.* ||| | `-DMLPACK_ENABLE_ANN_SERIALIZATION` | `#define MLPACK_ENABLE_ANN_SERIALIZATION` | Allow neural network layers to be serialized. | -| `-DMLPACK_DISABLE_STB` | `#define MLPACK_DISABLE_STB` | Disable [STB](https://github.com/nothings/stb)-related [image functionality](load_save.md#image-data). | | `-DMLPACK_NO_STD_MUTEX` | `#define MLPACK_NO_STD_MUTEX` | Disable mutexes inside mlpack; use this if your system has no support for `std::mutex` and has only one core. You may also need to define `ARMA_DO_NOT_USE_STD_MUTEX` for Armadillo. | +|---------------------------|-------------------|---------------| +|*Configuration.* ||| +| `-DMLPACK_USE_SYSTEM_STB` | `#define MLPACK_USE_SYSTEM_STB` | Use the version of STB available on the system instead of the version bundled with mlpack. If set, make sure `stb_image.h`, `stb_image_write.h`, and `stb_image_resize2.h` are available. | +| `-DMLPACK_DONT_USE_SYSTEM_STB` | `#define MLPACK_DONT_USE_SYSTEM_STB` | Force usage of the bundled version of STB. Only necessary if mlpack was [configured](install.md#cmake-options) with `USE_SYSTEM_STB=ON`. | ***Note:*** If your code serializes (saves or loads) mlpack neural networks, the `MLPACK_ENABLE_ANN_SERIALIZATION` option must be enabled. This option is not diff --git a/doc/user/install.md b/doc/user/install.md index f87c670009..0f8b362baf 100644 --- a/doc/user/install.md +++ b/doc/user/install.md @@ -194,6 +194,7 @@ The following options can be used when configuring mlpack. | `-DBUILD_TESTS=ON` | Build `mlpack_test`. | `OFF` | | `-DUSE_OPENMP=ON` | Use OpenMP for parallelization. | `ON` | | `-DUSE_PRECOMPILED_HEADERS=OFF` | Disable precompiled headers during build. | `OFF` | +| `-DUSE_SYSTEM_STB=OFF` | Use version of STB bundled with mlpack. If set to `ON` make sure `stb_image.h`, `stb_image_write.h`, and `stb_image_resize2.h` are available. | `OFF` | |--------------|-------------------|---------------| | ***Dependency locations*** ||| | `-DARMADILLO_INCLUDE_DIR=/path/to/arma/include/` | Path containing `armadillo` header file. || diff --git a/doc/user/load_save.md b/doc/user/load_save.md index 4a7e76cc5d..358aec69c8 100644 --- a/doc/user/load_save.md +++ b/doc/user/load_save.md @@ -523,6 +523,92 @@ outImages.push_back("bandicoot-favicon-inv.jpeg"); mlpack::data::Save(outImages, matrix, info); ``` +### Resize images + +It is possible to resize images in mlpack with the following function: + +- `ResizeImages(images, info, newWidth, newHeight)` + * `images` is a [column-major matrix](matrices.md) containing a set of + images; each image is represented as a flattened vector in one column. + + * `info` is a [`data::ImageInfo&`](#dataimageinfo) containing details about + the images in `images`, and will be modified to contain the new size of the + images. + + * `newWidth` and `newHeight` (of type `size_t`) are the desired new + dimensions of the resized images. + + * This function returns `void` and modifies `info` and `images`. + + * ***NOTE:*** if the element type of `images` is not `unsigned char` or + `float` (e.g. if `image` is not `arma::Mat` or + `arma::fmat`), the matrix will be temporarily converted during resizing; + therefore, using `unsigned char` or `float` as the element type is the most + efficient. + + * This function expects all the images to have identical + dimensions. If this is not the case, iteratively call `ResizeImages()` with + a single image/column in `images`. + +Example usage of the `ResizeImages()` function on a set of images with +different dimensions: + +```c++ +// See https://datasets.mlpack.org/sheep.tar.bz2 +arma::Mat image; +mlpack::data::ImageInfo info; + +// The images are located in our test/data directory. However, any image could +// be used instead. +std::vector files = + {"sheep_1.jpg", "sheep_2.jpg", "sheep_3.jpg", "sheep_4.jpg", + "sheep_5.jpg", "sheep_6.jpg"}; + +// The resized images will be saved locally. We are declaring the vector that +// contains the names of the resized images. +std::vector reSheeps = + {"re_sheep_1.jpg", "re_sheep_2.jpg", "re_sheep_3.jpg", "re_sheep_4.jpg", + "re_sheep_5.jpg", "re_sheep_6.jpg"}; + +// Load and Resize each one of them individually, because they do not have +// the same dimensions. The `info` will contain the dimension for each one. +for (size_t i = 0; i < files.size(); i++) +{ + mlpack::data::Load(files.at(i), image, info, false); + mlpack::data::ResizeImages(image, info, 320, 320); + mlpack::data::Save(reSheeps.at(i), image, info, false); +} +``` + +Example usage of `ResizeImages()` function on a set of images that have the +same dimensions. + +```c++ +// All images have the same dimension, It would be possible to load all of +// them into one matrix + +// See https://datasets.mlpack.org/sheep.tar.bz2 +arma::Mat images; +mlpack::data::ImageInfo info; + +std::vector reSheeps = + {"re_sheep_1.jpg", "re_sheep_2.jpg", "re_sheep_3.jpg", "re_sheep_4.jpg", + "re_sheep_5.jpg", "re_sheep_6.jpg"}; + +mlpack::data::Load(reSheeps, images, info, false); + +// Now let us resize all these images at once, to specific dimensions. +mlpack::data::ResizeImages(images, info, 160, 160); + +// The resized images will be saved locally. We are declaring the vector that +// contains the names of the resized images. +std::vector smSheeps = + {"sm_sheep_1.jpg", "sm_sheep_2.jpg", "sm_sheep_3.jpg", "sm_sheep_4.jpg", + "sm_sheep_5.jpg", "sm_sheep_6.jpg"}; + +mlpack::data::Save(smSheeps, images, info, false); +``` + ## mlpack objects All mlpack objects can be saved with `data::Save()` and loaded with diff --git a/scripts/test-docs.sh b/scripts/test-docs.sh index 31bb75a9d9..ceccc0ab91 100755 --- a/scripts/test-docs.sh +++ b/scripts/test-docs.sh @@ -239,7 +239,7 @@ download_http_artifacts() sed 's/^.*\(http[^ ]*\).*$/\1/' |\ sort |\ uniq |\ - grep 'csv\|arff\|bin\|png' |\ + grep 'csv\|arff\|bin\|png\|jpg\|bz2\|gz' |\ sed 's/\.$//'`; cd $output_dir; for a in $artifacts; @@ -253,6 +253,18 @@ download_http_artifacts() echo "Error downloading $a!"; exit 1; fi + + if [[ $a == *.gz ]]; + then + echo "Unpacking $a..."; + tar -xzpf *.gz; + fi + + if [[ $a == *.bz2 ]]; + then + echo "Unpacking $a..."; + tar -xjpf *.bz2; + fi fi done cd - >/dev/null; diff --git a/src/mlpack/bindings/R/CMakeLists.txt b/src/mlpack/bindings/R/CMakeLists.txt index 8cb09093c0..1733b936c3 100644 --- a/src/mlpack/bindings/R/CMakeLists.txt +++ b/src/mlpack/bindings/R/CMakeLists.txt @@ -403,7 +403,8 @@ macro (post_r_setup) # Collect all header and source files in the library. file(GLOB_RECURSE R_SRC_HPP_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.hpp) file(GLOB_RECURSE R_SRC_CPP_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.cpp) - set(R_SRC_FILES ${R_SRC_HPP_FILES} ${R_SRC_CPP_FILES}) + file(GLOB_RECURSE R_SRC_H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.h) + set(R_SRC_FILES ${R_SRC_HPP_FILES} ${R_SRC_CPP_FILES} ${R_SRC_H_FILES}) # In case of R_Bindings we are copying all of these header to # /src/cereal/ because the currently-packaged version diff --git a/src/mlpack/config.hpp b/src/mlpack/config.hpp index a8a03c3c93..7747cd6401 100644 --- a/src/mlpack/config.hpp +++ b/src/mlpack/config.hpp @@ -23,29 +23,6 @@ // #define MLPACK_HAS_BFD_DL #endif -// -// mlpack provides image loading and saving support via STB, if available. STB -// is an optional dependency of mlpack. When STB is found on a system, -// MLPACK_HAS_STB will be defined and the files `stb_image.h` and -// `stb_image_write.h` are expected to be found in the compiler include path. -// -#ifndef MLPACK_HAS_STB -// #define MLPACK_HAS_STB -#endif - -// -// If STB support is available but the STB headers do not live in an stb/ -// directory, then MLPACK_HAS_NO_STB_DIR should be defined. -// -// Note that this is ignored in newer compilers where __has_include is available -// (C++17 and newer compilers support it). -// -#ifdef MLPACK_HAS_STB -#ifndef MLPACK_HAS_NO_STB_DIR -// #define MLPACK_HAS_NO_STB_DIR -#endif -#endif - // // If the version of mlpack is built from a git repository and is not an // official release, then MLPACK_GIT_VERSION will be defined. This causes @@ -82,41 +59,18 @@ #endif // -// Perform autodetection of STB if possible. +// MLPACK_USE_SYSTEM_STB is used to enable usage of locally installed STB. // -#ifndef MLPACK_HAS_STB - #if defined __has_include - #if __has_include("stb_image.h") - #define MLPACK_HAS_STB_IMAGE - #elif __has_include("stb/stb_image.h") - #define MLPACK_HAS_STB_IMAGE - #endif - - #if __has_include("stb_image_write.h") - #define MLPACK_HAS_STB_IMAGE_WRITE - #elif __has_include("stb/stb_image_write.h") - #define MLPACK_HAS_STB_IMAGE_WRITE - #endif - - #if defined(MLPACK_HAS_STB_IMAGE) && defined(MLPACK_HAS_STB_IMAGE_WRITE) - #define MLPACK_HAS_STB - #endif - - #undef MLPACK_HAS_STB_IMAGE - #undef MLPACK_HAS_STB_IMAGE_WRITE - #endif +#if !defined(MLPACK_USE_SYSTEM_STB) + // #define MLPACK_USE_SYSTEM_STB #endif // -// These macros can be defined to disable support that is defined above. (This -// is useful if you cannot or do not want to modify config.hpp.) +// This is necessary if we would like to overwrite the default packaging +// condition. // -#ifdef MLPACK_DISABLE_STB - #undef MLPACK_HAS_STB -#endif - -#ifdef MLPACK_DISABLE_NO_STB_DIR - #undef MLPACK_HAS_NO_STB_DIR +#if defined(MLPACK_DONT_USE_SYSTEM_STB) && defined(MLPACK_USE_SYSTEM_STB) + #undef MLPACK_USE_SYSTEM_STB #endif #ifdef MLPACK_DISABLE_BFD_DL diff --git a/src/mlpack/core.hpp b/src/mlpack/core.hpp index 7205587ab5..ede31bc50b 100644 --- a/src/mlpack/core.hpp +++ b/src/mlpack/core.hpp @@ -35,6 +35,7 @@ #include // Now the core mlpack classes. +#include #include #include #include diff --git a/src/mlpack/core/data/data.hpp b/src/mlpack/core/data/data.hpp index 5deb5c749e..b642ba2bf5 100644 --- a/src/mlpack/core/data/data.hpp +++ b/src/mlpack/core/data/data.hpp @@ -31,6 +31,7 @@ #include "confusion_matrix.hpp" #include "dataset_mapper.hpp" #include "image_info.hpp" +#include "image_resize_crop.hpp" #include "imputer.hpp" #include "is_naninf.hpp" #include "normalize_labels.hpp" diff --git a/src/mlpack/core/data/image_info_impl.hpp b/src/mlpack/core/data/image_info_impl.hpp index 7c312009ec..629febcd8b 100644 --- a/src/mlpack/core/data/image_info_impl.hpp +++ b/src/mlpack/core/data/image_info_impl.hpp @@ -30,8 +30,6 @@ inline const std::vector SaveFileTypes() } // namespace data } // namespace mlpack -#ifdef MLPACK_HAS_STB // Compile this only if stb is present. - // In case it hasn't been included yet. #include "image_info.hpp" @@ -65,8 +63,6 @@ inline bool ImageFormatSupported(const std::string& fileName, const bool save) } // namespace data } // namespace mlpack -#endif // MLPACK_HAS_STB. - namespace mlpack { namespace data { diff --git a/src/mlpack/core/data/image_resize_crop.hpp b/src/mlpack/core/data/image_resize_crop.hpp new file mode 100644 index 0000000000..4be6bdecd6 --- /dev/null +++ b/src/mlpack/core/data/image_resize_crop.hpp @@ -0,0 +1,135 @@ +/** + * @file core/data/image_resize_crop.hpp + * @author Omar Shrit + * + * Image resize and crop functionalities. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MLPACK_CORE_DATA_IMAGE_RESIZE_CROP_HPP +#define MLPACK_CORE_DATA_IMAGE_RESIZE_CROP_HPP + +#include +#include + +#include "image_info.hpp" + +namespace mlpack { +namespace data { + +/** + * Image resize/crop interfaces. + */ + +/** + * Resize one single image matrix or a set of images. + * + * This function should be used if the image is loaded as an armadillo matrix + * and the number of cols equal to the Width and the number of rows equal + * the Height of the image, or the total number of image pixels is equal to the + * number of element in an armadillo matrix. + * + * The same applies if a set of images is loaded, but all of them need to have + * identical dimension when loaded to this matrix. + * + * @param image The input matrix that contains the image to be resized. + * @param info Contains relevant input images information. + * @param newWidth The new requested width for the resized image. + * @param newHeight The new requested height for the resized image. + */ +template +inline void ResizeImages(arma::Mat& images, data::ImageInfo& info, + const size_t newWidth, const size_t newHeight) +{ + // First check if we are resizing one image or a group of images, the check + // is going to be different depending on the dimension. + // If the user would like to resize a set of images of different dimensions, + // then they need to consider passing them image by image. Otherwise, as + // assume that all images have identical dimension and need to be resized. + if (images.n_cols == 1) + { + if (images.n_elem != (info.Width() * info.Height() * info.Channels())) + { + Log::Fatal << "ResizeImages(): dimensions mismatch: the number of pixels " + << "is not equal to the dimension provided by the given ImageInfo." + << std::endl; + } + } + else + { + if (images.n_rows != (info.Width() * info.Height() * info.Channels())) + { + Log::Fatal << "ResizeImages(): dimension mismatch: in the case of " + << "several images, please check that all the images have the same " + << "dimensions; if not, load each image in one column and call this " + << "function iteratively." << std::endl; + } + } + + stbir_pixel_layout channels; + if (info.Channels() == 1) + { + channels = STBIR_1CHANNEL; + } + else if (info.Channels() == 3) + { + channels = STBIR_RGB; + } + + // This is required since STB only accept unsigned chars. + // set the new matrix size for copy + size_t newDimension = newWidth * newHeight * info.Channels(); + arma::Mat resizedFloatImages; + arma::Mat resizedImages; + + // This is not optimal, but I do not want to allocate memory for nothing. + if (std::is_same::value) + resizedFloatImages.set_size(newDimension, images.n_cols); + else + resizedImages.set_size(newDimension, images.n_cols); + + for (size_t i = 0; i < images.n_cols; ++i) + { + if constexpr (std::is_same::value) + { + stbir_resize_uint8_linear(images.colptr(i), info.Width(), info.Height(), + 0, resizedImages.colptr(i), newWidth, newHeight, 0, channels); + } + else if constexpr (std::is_same::value) + { + stbir_resize_float_linear(images.colptr(i), info.Width(), info.Height(), + 0, resizedFloatImages.colptr(i), newWidth, newHeight, 0, channels); + } + else + { + arma::Mat tempSrc = + arma::conv_to>::from(images); + + stbir_resize_uint8_linear(tempSrc.colptr(i), info.Width(), info.Height(), + 0, resizedImages.colptr(i), newWidth, newHeight, 0, channels); + } + } + + if (std::is_same::value) + { + // The conv_to is needed here so that this code compiles even when this + // branch isn't taken. + images = arma::conv_to>::from(std::move(resizedFloatImages)); + } + else + { + images = arma::conv_to>::from(std::move(resizedImages)); + } + info.Width() = newWidth; + info.Height() = newHeight; +} + +} // namespace data +} // namespace mlpack + +#endif + diff --git a/src/mlpack/core/data/load_image.hpp b/src/mlpack/core/data/load_image.hpp index 1c76805003..d79590f14f 100644 --- a/src/mlpack/core/data/load_image.hpp +++ b/src/mlpack/core/data/load_image.hpp @@ -13,34 +13,10 @@ #ifndef MLPACK_CORE_DATA_LOAD_IMAGE_HPP #define MLPACK_CORE_DATA_LOAD_IMAGE_HPP +#include + #include "image_info.hpp" -#ifdef MLPACK_HAS_STB - -// The definition of STB_IMAGE_IMPLEMENTATION means that the implementation will -// be included here directly. -#define STB_IMAGE_STATIC -#define STB_IMAGE_IMPLEMENTATION - -#if defined __has_include - #if __has_include("stb_image.h") - #include "stb_image.h" - #elif __has_include("stb/stb_image.h") - #include "stb/stb_image.h" - #else - #undef MLPACK_HAS_STB - #pragma message("Warning: STB disabled; stb_image.h header not found") - #endif -#else - #ifdef MLPACK_HAS_STB_DIR - #include "stb/stb_image.h" - #else - #include "stb_image.h" - #endif -#endif - -#endif // MLPACK_HAS_STB - namespace mlpack { namespace data { diff --git a/src/mlpack/core/data/load_image_impl.hpp b/src/mlpack/core/data/load_image_impl.hpp index a86b84eddf..de19eca952 100644 --- a/src/mlpack/core/data/load_image_impl.hpp +++ b/src/mlpack/core/data/load_image_impl.hpp @@ -90,8 +90,6 @@ bool Load(const std::vector& files, return true; } -#ifdef MLPACK_HAS_STB - inline bool LoadImage(const std::string& filename, arma::Mat& matrix, ImageInfo& info, @@ -167,29 +165,6 @@ inline bool LoadImage(const std::string& filename, return true; } -#else // MLPACK_HAS_STB - -inline bool LoadImage(const std::string& /* filename */, - arma::Mat& /* matrix */, - ImageInfo& /* info */, - const bool fatal) -{ - if (fatal) - { - Log::Fatal << "Load(): mlpack was not compiled with STB support, so images " - << "cannot be loaded!" << std::endl; - } - else - { - Log::Warn << "Load(): mlpack was not compiled with STB support, so images " - << "cannot be loaded!" << std::endl; - } - - return false; -} - -#endif - } // namespace data } // namespace mlpack diff --git a/src/mlpack/core/data/save_image.hpp b/src/mlpack/core/data/save_image.hpp index 5be345a3bb..233d286839 100644 --- a/src/mlpack/core/data/save_image.hpp +++ b/src/mlpack/core/data/save_image.hpp @@ -12,32 +12,10 @@ #ifndef MLPACK_CORE_DATA_SAVE_IMAGE_HPP #define MLPACK_CORE_DATA_SAVE_IMAGE_HPP +#include + #include "image_info.hpp" -#ifdef MLPACK_HAS_STB - -#define STB_IMAGE_WRITE_STATIC -#define STB_IMAGE_WRITE_IMPLEMENTATION - -#if defined __has_include - #if __has_include("stb_image_write.h") - #include "stb_image_write.h" - #elif __has_include("stb/stb_image_write.h") - #include "stb/stb_image_write.h" - #else - #undef MLPACK_HAS_STB - #pragma message("Warning: STB disabled; stb_image_write.h header not found") - #endif -#else - #ifdef MLPACK_HAS_STB_DIR - #include "stb/stb_image_write.h" - #else - #include "stb_image_write.h" - #endif -#endif - -#endif // MLPACK_HAS_STB - namespace mlpack { namespace data { diff --git a/src/mlpack/core/data/save_image_impl.hpp b/src/mlpack/core/data/save_image_impl.hpp index e14d56bcb4..1802dcef83 100644 --- a/src/mlpack/core/data/save_image_impl.hpp +++ b/src/mlpack/core/data/save_image_impl.hpp @@ -75,8 +75,6 @@ bool Save(const std::vector& files, return status; } -#ifdef MLPACK_HAS_STB - inline bool SaveImage(const std::string& filename, arma::Mat& image, ImageInfo& info, @@ -166,29 +164,6 @@ inline bool SaveImage(const std::string& filename, return status; } -#else // MLPACK_HAS_STB - -inline bool SaveImage(const std::string& /* filename */, - arma::Mat& /* image */, - ImageInfo& /* info */, - const bool fatal) -{ - if (fatal) - { - Log::Fatal << "Save(): mlpack was not compiled with STB support, so images " - << "cannot be saved!" << std::endl; - } - else - { - Log::Warn << "Save(): mlpack was not compiled with STB support, so images " - << "cannot be saved!" << std::endl; - } - - return false; -} - -#endif - } // namespace data } // namespace mlpack diff --git a/src/mlpack/core/stb/bundled/stb_image.h b/src/mlpack/core/stb/bundled/stb_image.h new file mode 100644 index 0000000000..9eedabedc4 --- /dev/null +++ b/src/mlpack/core/stb/bundled/stb_image.h @@ -0,0 +1,7988 @@ +/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_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 STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.30 (2024-05-31) avoid erroneous gcc warning + 2.29 (2023-05-xx) optimizations + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data); +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif + + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + int ch; + fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); +#endif + +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +#ifndef STBI_NO_FAILURE_STRINGS +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} +#endif + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} +#endif + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} +#endif + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load_global = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 8) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 16) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else +static void stbi__skip(stbi__context *s, int n) +{ + if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} +#endif + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { + h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + j->marker = stbi__skip_jpeg_junk_at_end(j); + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); + } else { + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); + } + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + int hit_zeof_once; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); + } + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; + } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } + return 1; + } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (len > a->zout_end - zout) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } else if (c == 18) { + c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + a->hit_zeof_once = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub +}; + +static int stbi__paeth(int a, int b, int c) +{ + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16 ? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + + for (j=0; j < y; ++j) { + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; + int filter = *raw++; + + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; + } + + raw += nk; + + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; + + // expand bits to bytes first + if (depth == 4) { + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; + } + } else if (depth == 2) { + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; + } + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; + } + } + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); + if (img_n == 1) { + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; + } + } else { + STBI_ASSERT(img_n == 3); + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; + } + } + } + } + } + + STBI_FREE(filter_buf); + if (!all_ok) return 0; + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_global = flag_true_if_should_convert; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + // even with SCAN_header, have to scan to see if we have a tRNS + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } + if (z->depth == 16) { + for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning + tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n && k < 3; ++k) + tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; + int extra_read; +} stbi__bmp_data; + +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - info.extra_read - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + + if (delays) { + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) + return 0; + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } + + if (req_comp && req_comp != s->img_n) { + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; + else + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +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. +------------------------------------------------------------------------------ +*/ diff --git a/src/mlpack/core/stb/bundled/stb_image_resize2.h b/src/mlpack/core/stb/bundled/stb_image_resize2.h new file mode 100644 index 0000000000..d07676f7f6 --- /dev/null +++ b/src/mlpack/core/stb/bundled/stb_image_resize2.h @@ -0,0 +1,10601 @@ +/* stb_image_resize2 - v2.12 - public domain image resizing + + by Jeff Roberts (v2) and Jorge L Rodriguez + http://github.com/nothings/stb + + Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only + scaling and translation is supported, no rotations or shears. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + EASY API CALLS: + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation, clamps to edge. + + stbir_resize_uint8_srgb( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + stbir_resize_uint8_linear( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + stbir_resize_float_linear( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + If you pass NULL or zero for the output_pixels, we will allocate the output buffer + for you and return it from the function (free with free() or STBIR_FREE). + As a special case, XX_stride_in_bytes of 0 means packed continuously in memory. + + API LEVELS + There are three levels of API - easy-to-use, medium-complexity and extended-complexity. + + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + MEMORY ALLOCATION + By default, we use malloc and free for memory allocation. To override the + memory allocation, before the implementation #include, add a: + + #define STBIR_MALLOC(size,user_data) ... + #define STBIR_FREE(ptr,user_data) ... + + Each resize makes exactly one call to malloc/free (unless you use the + extended API where you can do one allocation for many resizes). Under + address sanitizer, we do separate allocations to find overread/writes. + + PERFORMANCE + This library was written with an emphasis on performance. When testing + stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with + STBIR_TYPE_UINT8 pixels and CLAMPed edges (which is what many other resize + libs do by default). Also, make sure SIMD is turned on of course (default + for 64-bit targets). Avoid WRAP edge mode if you want the fastest speed. + + This library also comes with profiling built-in. If you define STBIR_PROFILE, + you can use the advanced API and get low-level profiling information by + calling stbir_resize_extended_profile_info() or stbir_resize_split_profile_info() + after a resize. + + SIMD + Most of the routines have optimized SSE2, AVX, NEON and WASM versions. + + On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and + ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or + STBIR_NEON. For AVX and AVX2, we auto-select it by detecting the /arch:AVX + or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2 + support on by defining STBIR_SSE2, STBIR_AVX or STBIR_AVX2. + + On Linux, SSE2 and Neon is on by default for 64-bit x64 or ARM64. For 32-bit, + we select x86 SIMD mode by whether you have -msse2, -mavx or -mavx2 enabled + on the command line. For 32-bit ARM, you must pass -mfpu=neon-vfpv4 for both + clang and GCC, but GCC also requires an additional -mfp16-format=ieee to + automatically enable NEON. + + On x86 platforms, you can also define STBIR_FP16C to turn on FP16C instructions + for converting back and forth to half-floats. This is autoselected when we + are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses + the built-in half float hardware NEON instructions. + + You can also tell us to use multiply-add instructions with STBIR_USE_FMA. + Because x86 doesn't always have fma, we turn it off by default to maintain + determinism across all platforms. If you don't care about non-FMA determinism + and are willing to restrict yourself to more recent x86 CPUs (around the AVX + timeframe), then fma will give you around a 15% speedup. + + You can force off SIMD in all cases by defining STBIR_NO_SIMD. You can turn + off AVX or AVX2 specifically with STBIR_NO_AVX or STBIR_NO_AVX2. AVX is 10% + to 40% faster, and AVX2 is generally another 12%. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how the alpha + channel of an image is processed. + + When alpha represents transparency, it is important that when combining + colors with filtering, the pixels should not be treated equally; they + should use a weighted average based on their alpha values. For example, + if a pixel is 1% opaque bright green and another pixel is 99% opaque + black and you average them, the average will be 50% opaque, but the + unweighted average and will be a middling green color, while the weighted + average will be nearly black. This means the unweighted version introduced + green energy that didn't exist in the source image. + + (If you want to know why this makes sense, you can work out the math for + the following: consider what happens if you alpha composite a source image + over a fixed color and then average the output, vs. if you average the + source image pixels and then composite that over the same fixed color. + Only the weighted average produces the same result as the ground truth + composite-then-average result.) + + Therefore, it is in general best to "alpha weight" the pixels when applying + filters to them. This essentially means multiplying the colors by the alpha + values before combining them, and then dividing by the alpha value at the + end. + + The computer graphics industry introduced a technique called "premultiplied + alpha" or "associated alpha" in which image colors are stored in image files + already multiplied by their alpha. This saves some math when compositing, + and also avoids the need to divide by the alpha at the end (which is quite + inefficient). However, while premultiplied alpha is common in the movie CGI + industry, it is not commonplace in other industries like videogames, and most + consumer file formats are generally expected to contain not-premultiplied + colors. For example, Photoshop saves PNG files "unpremultiplied", and web + browsers like Chrome and Firefox expect PNG images to be unpremultiplied. + + Note that there are three possibilities that might describe your image + and resize expectation: + + 1. images are not premultiplied, alpha weighting is desired + 2. images are not premultiplied, alpha weighting is not desired + 3. images are premultiplied + + Both case #2 and case #3 require the exact same math: no alpha weighting + should be applied or removed. Only case 1 requires extra math operations; + the other two cases can be handled identically. + + stb_image_resize expects case #1 by default, applying alpha weighting to + images, expecting the input images to be unpremultiplied. This is what the + COLOR+ALPHA buffer types tell the resizer to do. + + When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, + STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are + non-premultiplied. In these cases, the resizer will alpha weight the colors + (effectively creating the premultiplied image), do the filtering, and then + convert back to non-premult on exit. + + When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM, + STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels + ARE premultiplied. In this case, the resizer doesn't have to do the + premultipling - it can filter directly on the input. This about twice as + fast as the non-premultiplied case, so it's the right option if your data is + already setup correctly. + + When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are + telling us that there is no channel that represents transparency; it may be + RGB and some unrelated fourth channel that has been stored in the alpha + channel, but it is actually not alpha. No special processing will be + performed. + + The difference between the generic 4 or 2 channel layouts, and the + specialized _PM versions is with the _PM versions you are telling us that + the data *is* alpha, just don't premultiply it. That's important when + using SRGB pixel formats, we need to know where the alpha is, because + it is converted linearly (rather than with the SRGB converters). + + Because alpha weighting produces the same effect as premultiplying, you + even have the option with non-premultiplied inputs to let the resizer + produce a premultiplied output. Because the intially computed alpha-weighted + output image is effectively premultiplied, this is actually more performant + than the normal path which un-premultiplies the output image as a final step. + + Finally, when converting both in and out of non-premulitplied space (for + example, when using STBIR_RGBA), we go to somewhat heroic measures to + ensure that areas with zero alpha value pixels get something reasonable + in the RGB values. If you don't care about the RGB values of zero alpha + pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality() + function - this runs a premultiplied resize about 25% faster. That said, + when you really care about speed, using premultiplied pixels for both in + and out (STBIR_RGBA_PM, etc) much faster than both of these premultiplied + options. + + PIXEL LAYOUT CONVERSION + The resizer can convert from some pixel layouts to others. When using the + stbir_set_pixel_layouts(), you can, for example, specify STBIR_RGBA + on input, and STBIR_ARGB on output, and it will re-organize the channels + during the resize. Currently, you can only convert between two pixel + layouts with the same number of channels. + + DETERMINISM + We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc). + This requires compiling with fast-math off (using at least /fp:precise). + Also, you must turn off fp-contracting (which turns mult+adds into fmas)! + We attempt to do this with pragmas, but with Clang, you usually want to add + -ffp-contract=off to the command line as well. + + For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is, + if the scalar x87 unit gets used at all, we immediately lose determinism. + On Microsoft Visual Studio 2008 and earlier, from what we can tell there is + no way to be deterministic in 32-bit x86 (some x87 always leaks in, even + with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and + -fpmath=sse. + + Note that we will not be deterministic with float data containing NaNs - + the NaNs will propagate differently on different SIMD and platforms. + + If you turn on STBIR_USE_FMA, then we will be deterministic with other + fma targets, but we will differ from non-fma targets (this is unavoidable, + because a fma isn't simply an add with a mult - it also introduces a + rounding difference compared to non-fma instruction sequences. + + FLOAT PIXEL FORMAT RANGE + Any range of values can be used for the non-alpha float data that you pass + in (0 to 1, -1 to 1, whatever). However, if you are inputting float values + but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we + scale back properly. The alpha channel must also be 0 to 1 for any format + that does premultiplication prior to resizing. + + Note also that with float output, using filters with negative lobes, the + output filtered values might go slightly out of range. You can define + STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range + to clamp to on output, if that's important. + + MAX/MIN SCALE FACTORS + The input pixel resolutions are in integers, and we do the internal pointer + resolution in size_t sized integers. However, the scale ratio from input + resolution to output resolution is calculated in float form. This means + the effective possible scale ratio is limited to 24 bits (or 16 million + to 1). As you get close to the size of the float resolution (again, 16 + million pixels wide or high), you might start seeing float inaccuracy + issues in general in the pipeline. If you have to do extreme resizes, + you can usually do this is multiple stages (using float intermediate + buffers). + + FLIPPED IMAGES + Stride is just the delta from one scanline to the next. This means you can + use a negative stride to handle inverted images (point to the final + scanline and use a negative stride). You can invert the input or output, + using negative strides. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters to + use, you can change the compile-time defaults with: + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are supplied. For a list of supported + filters, see the stbir_filter enum. You can install your own filters by + using the stbir_set_filter_callbacks function. + + PROGRESS + For interactive use with slow resize operations, you can use the the + scanline callbacks in the extended API. It would have to be a *very* large + image resample to need progress though - we're very fast. + + CEIL and FLOOR + In scalar mode, the only functions we use from math.h are ceilf and floorf, + but if you have your own versions, you can define the STBIR_CEILF(v) and + STBIR_FLOORF(v) macros and we'll use them instead. In SIMD, we just use + our own versions. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + PORTING FROM VERSION 1 + The API has changed. You can continue to use the old version of stb_image_resize.h, + which is available in the "deprecated/" directory. + + If you're using the old simple-to-use API, porting is straightforward. + (For more advanced APIs, read the documentation.) + + stbir_resize_uint8(): + - call `stbir_resize_uint8_linear`, cast channel count to `stbir_pixel_layout` + + stbir_resize_float(): + - call `stbir_resize_float_linear`, cast channel count to `stbir_pixel_layout` + + stbir_resize_uint8_srgb(): + - function name is unchanged + - cast channel count to `stbir_pixel_layout` + - above is sufficient unless your image has alpha and it's not RGBA/BGRA + - in that case, follow the below instructions for stbir_resize_uint8_srgb_edgemode + + stbir_resize_uint8_srgb_edgemode() + - switch to the "medium complexity" API + - stbir_resize(), very similar API but a few more parameters: + - pixel_layout: cast channel count to `stbir_pixel_layout` + - data_type: STBIR_TYPE_UINT8_SRGB + - edge: unchanged (STBIR_EDGE_WRAP, etc.) + - filter: STBIR_FILTER_DEFAULT + - which channel is alpha is specified in stbir_pixel_layout, see enum for details + + FUTURE TODOS + * For polyphase integral filters, we just memcpy the coeffs to dupe + them, but we should indirect and use the same coeff memory. + * Add pixel layout conversions for sensible different channel counts + (maybe, 1->3/4, 3->4, 4->1, 3->1). + * For SIMD encode and decode scanline routines, do any pre-aligning + for bad input/output buffer alignments and pitch? + * For very wide scanlines, we should we do vertical strips to stay within + L2 cache. Maybe do chunks of 1K pixels at a time. There would be + some pixel reconversion, but probably dwarfed by things falling out + of cache. Probably also something possible with alternating between + scattering and gathering at high resize scales? + * Rewrite the coefficient generator to do many at once. + * AVX-512 vertical kernels - worried about downclocking here. + * Convert the reincludes to macros when we know they aren't changing. + * Experiment with pivoting the horizontal and always using the + vertical filters (which are faster, but perhaps not enough to overcome + the pivot cost and the extra memory touches). Need to buffer the whole + image so have to balance memory use. + * Most of our code is internally function pointers, should we compile + all the SIMD stuff always and dynamically dispatch? + + CONTRIBUTORS + Jeff Roberts: 2.0 implementation, optimizations, SIMD + Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer + Fabian Giesen: half float and srgb converters + Sean Barrett: API design, optimizations + Jorge L Rodriguez: Original 1.0 implementation + Aras Pranckevicius: bugfixes + Nathan Reed: warning fixes for 1.0 + + REVISIONS + 2.12 (2024-10-18) fix incorrect use of user_data with STBIR_FREE + 2.11 (2024-09-08) fix harmless asan warnings in 2-channel and 3-channel mode + with AVX-2, fix some weird scaling edge conditions with + point sample mode. + 2.10 (2024-07-27) fix the defines GCC and mingw for loop unroll control, + fix MSVC 32-bit arm half float routines. + 2.09 (2024-06-19) fix the defines for 32-bit ARM GCC builds (was selecting + hardware half floats). + 2.08 (2024-06-10) fix for RGB->BGR three channel flips and add SIMD (thanks + to Ryan Salsbury), fix for sub-rect resizes, use the + pragmas to control unrolling when they are available. + 2.07 (2024-05-24) fix for slow final split during threaded conversions of very + wide scanlines when downsampling (caused by extra input + converting), fix for wide scanline resamples with many + splits (int overflow), fix GCC warning. + 2.06 (2024-02-10) fix for identical width/height 3x or more down-scaling + undersampling a single row on rare resize ratios (about 1%). + 2.05 (2024-02-07) fix for 2 pixel to 1 pixel resizes with wrap (thanks Aras), + fix for output callback (thanks Julien Koenen). + 2.04 (2023-11-17) fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic). + 2.03 (2023-11-01) ASAN and TSAN warnings fixed, minor tweaks. + 2.00 (2023-10-10) mostly new source: new api, optimizations, simd, vertical-first, etc + 2x-5x faster without simd, 4x-12x faster with simd, + in some cases, 20x to 40x faster esp resizing large to very small. + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. +*/ + +#if !defined(STB_IMAGE_RESIZE_DO_HORIZONTALS) && !defined(STB_IMAGE_RESIZE_DO_VERTICALS) && !defined(STB_IMAGE_RESIZE_DO_CODERS) // for internal re-includes + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE2_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE2_H + +#include +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +typedef unsigned __int64 stbir_uint64; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +typedef uint64_t stbir_uint64; +#endif + +#ifdef _M_IX86_FP +#if ( _M_IX86_FP >= 1 ) +#ifndef STBIR_SSE +#define STBIR_SSE +#endif +#endif +#endif + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2) + #ifndef STBIR_SSE2 + #define STBIR_SSE2 + #endif + #if defined(__AVX__) || defined(STBIR_AVX2) + #ifndef STBIR_AVX + #ifndef STBIR_NO_AVX + #define STBIR_AVX + #endif + #endif + #endif + #if defined(__AVX2__) || defined(STBIR_AVX2) + #ifndef STBIR_NO_AVX2 + #ifndef STBIR_AVX2 + #define STBIR_AVX2 + #endif + #if defined( _MSC_VER ) && !defined(__clang__) + #ifndef STBIR_FP16C // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c + #define STBIR_FP16C + #endif + #endif + #endif + #endif + #ifdef __F16C__ + #ifndef STBIR_FP16C // turn on FP16C instructions if the define is set (for clang and gcc) + #define STBIR_FP16C + #endif + #endif +#endif + +#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || ((__ARM_NEON_FP & 4) != 0) || defined(__ARM_NEON__) +#ifndef STBIR_NEON +#define STBIR_NEON +#endif +#endif + +#if defined(_M_ARM) || defined(__arm__) +#ifdef STBIR_USE_FMA +#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC +#endif +#endif + +#if defined(__wasm__) && defined(__wasm_simd128__) +#ifndef STBIR_WASM +#define STBIR_WASM +#endif +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +//// start "header file" /////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * stride is the offset between successive rows of image data +// in memory, in bytes. specify 0 for packed continuously in memory +// * colorspace is linear or sRGB as specified by function name +// * Uses the default filters +// * Uses edge mode clamped +// * returned result is 1 for success or 0 in case of an error. + + +// stbir_pixel_layout specifies: +// number of channels +// order of channels +// whether color is premultiplied by alpha +// for back compatibility, you can cast the old channel count to an stbir_pixel_layout +typedef enum +{ + STBIR_1CHANNEL = 1, + STBIR_2CHANNEL = 2, + STBIR_RGB = 3, // 3-chan, with order specified (for channel flipping) + STBIR_BGR = 0, // 3-chan, with order specified (for channel flipping) + STBIR_4CHANNEL = 5, + + STBIR_RGBA = 4, // alpha formats, where alpha is NOT premultiplied into color channels + STBIR_BGRA = 6, + STBIR_ARGB = 7, + STBIR_ABGR = 8, + STBIR_RA = 9, + STBIR_AR = 10, + + STBIR_RGBA_PM = 11, // alpha formats, where alpha is premultiplied into color channels + STBIR_BGRA_PM = 12, + STBIR_ARGB_PM = 13, + STBIR_ABGR_PM = 14, + STBIR_RA_PM = 15, + STBIR_AR_PM = 16, + + STBIR_RGBA_NO_AW = 11, // alpha formats, where NO alpha weighting is applied at all! + STBIR_BGRA_NO_AW = 12, // these are just synonyms for the _PM flags (which also do + STBIR_ARGB_NO_AW = 13, // no alpha weighting). These names just make it more clear + STBIR_ABGR_NO_AW = 14, // for some folks). + STBIR_RA_NO_AW = 15, + STBIR_AR_NO_AW = 16, + +} stbir_pixel_layout; + +//=============================================================== +// Simple-complexity API +// +// If output_pixels is NULL (0), then we will allocate the buffer and return it to you. +//-------------------------------- + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); +//=============================================================== + +//=============================================================== +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Can specify the datatype - U8, U8_SRGB, U16, FLOAT, HALF_FLOAT +// * Edge wrap can selected explicitly +// * Filter can be selected explicitly +//-------------------------------- + +typedef enum +{ + STBIR_EDGE_CLAMP = 0, + STBIR_EDGE_REFLECT = 1, + STBIR_EDGE_WRAP = 2, // this edge mode is slower and uses more memory + STBIR_EDGE_ZERO = 3, +} stbir_edge; + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 + STBIR_FILTER_POINT_SAMPLE = 6, // Simple point sampling + STBIR_FILTER_OTHER = 7, // User callback specified +} stbir_filter; + +typedef enum +{ + STBIR_TYPE_UINT8 = 0, + STBIR_TYPE_UINT8_SRGB = 1, + STBIR_TYPE_UINT8_SRGB_ALPHA = 2, // alpha channel, when present, should also be SRGB (this is very unusual) + STBIR_TYPE_UINT16 = 3, + STBIR_TYPE_FLOAT = 4, + STBIR_TYPE_HALF_FLOAT = 5 +} stbir_datatype; + +// medium api +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ); +//=============================================================== + + + +//=============================================================== +// Extended-complexity API +// +// This API exposes all resize functionality. +// +// * Separate filter types for each axis +// * Separate edge modes for each axis +// * Separate input and output data types +// * Can specify regions with subpixel correctness +// * Can specify alpha flags +// * Can specify a memory callback +// * Can specify a callback data type for pixel input and output +// * Can be threaded for a single resize +// * Can be used to resize many frames without recalculating the sampler info +// +// Use this API as follows: +// 1) Call the stbir_resize_init function on a local STBIR_RESIZE structure +// 2) Call any of the stbir_set functions +// 3) Optionally call stbir_build_samplers() if you are going to resample multiple times +// with the same input and output dimensions (like resizing video frames) +// 4) Resample by calling stbir_resize_extended(). +// 5) Call stbir_free_samplers() if you called stbir_build_samplers() +//-------------------------------- + + +// Types: + +// INPUT CALLBACK: this callback is used for input scanlines +typedef void const * stbir_input_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ); + +// OUTPUT CALLBACK: this callback is used for output scanlines +typedef void stbir_output_callback( void const * output_ptr, int num_pixels, int y, void * context ); + +// callbacks for user installed filters +typedef float stbir__kernel_callback( float x, float scale, void * user_data ); // centered at zero +typedef float stbir__support_callback( float scale, void * user_data ); + +// internal structure with precomputed scaling +typedef struct stbir__info stbir__info; + +typedef struct STBIR_RESIZE // use the stbir_resize_init and stbir_override functions to set these values for future compatibility +{ + void * user_data; + void const * input_pixels; + int input_w, input_h; + double input_s0, input_t0, input_s1, input_t1; + stbir_input_callback * input_cb; + void * output_pixels; + int output_w, output_h; + int output_subx, output_suby, output_subw, output_subh; + stbir_output_callback * output_cb; + int input_stride_in_bytes; + int output_stride_in_bytes; + int splits; + int fast_alpha; + int needs_rebuild; + int called_alloc; + stbir_pixel_layout input_pixel_layout_public; + stbir_pixel_layout output_pixel_layout_public; + stbir_datatype input_data_type; + stbir_datatype output_data_type; + stbir_filter horizontal_filter, vertical_filter; + stbir_edge horizontal_edge, vertical_edge; + stbir__kernel_callback * horizontal_filter_kernel; stbir__support_callback * horizontal_filter_support; + stbir__kernel_callback * vertical_filter_kernel; stbir__support_callback * vertical_filter_support; + stbir__info * samplers; +} STBIR_RESIZE; + +// extended complexity api + + +// First off, you must ALWAYS call stbir_resize_init on your resize structure before any of the other calls! +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, + const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero + stbir_pixel_layout pixel_layout, stbir_datatype data_type ); + +//=============================================================== +// You can update these parameters any time after resize_init and there is no cost +//-------------------------------- + +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ); +STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ); // no callbacks by default +STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ); // pass back STBIR_RESIZE* by default +STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ); + +//=============================================================== + + +//=============================================================== +// If you call any of these functions, you will trigger a sampler rebuild! +//-------------------------------- + +STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout ); // sets new buffer layouts +STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ); // CLAMP by default + +STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ); // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ); + +STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets both sub-regions (full regions by default) +STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ); // sets input sub-region (full region by default) +STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets output sub-region (full region by default) + +// when inputting AND outputting non-premultiplied alpha pixels, we use a slower but higher quality technique +// that fills the zero alpha pixel's RGB values with something plausible. If you don't care about areas of +// zero alpha, you can call this function to get about a 25% speed improvement for STBIR_RGBA to STBIR_RGBA +// types of resizes. +STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality ); +//=============================================================== + + +//=============================================================== +// You can call build_samplers to prebuild all the internal data we need to resample. +// Then, if you call resize_extended many times with the same resize, you only pay the +// cost once. +// If you do call build_samplers, you MUST call free_samplers eventually. +//-------------------------------- + +// This builds the samplers and does one allocation +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ); + +// You MUST call this, if you call stbir_build_samplers or stbir_build_samplers_with_splits +STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize ); +//=============================================================== + + +// And this is the main function to perform the resize synchronously on one thread. +STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ); + + +//=============================================================== +// Use these functions for multithreading. +// 1) You call stbir_build_samplers_with_splits first on the main thread +// 2) Then stbir_resize_with_split on each thread +// 3) stbir_free_samplers when done on the main thread +//-------------------------------- + +// This will build samplers for threading. +// You can pass in the number of threads you'd like to use (try_splits). +// It returns the number of splits (threads) that you can call it with. +/// It might be less if the image resize can't be split up that many ways. + +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits ); + +// This function does a split of the resizing (you call this fuction for each +// split, on multiple threads). A split is a piece of the output resize pixel space. + +// Note that you MUST call stbir_build_samplers_with_splits before stbir_resize_extended_split! + +// Usually, you will always call stbir_resize_split with split_start as the thread_index +// and "1" for the split_count. +// But, if you have a weird situation where you MIGHT want 8 threads, but sometimes +// only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the +// split_count each time to turn in into a 4 thread resize. (This is unusual). + +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ); +//=============================================================== + + +//=============================================================== +// Pixel Callbacks info: +//-------------------------------- + +// The input callback is super flexible - it calls you with the input address +// (based on the stride and base pointer), it gives you an optional_output +// pointer that you can fill, or you can just return your own pointer into +// your own data. +// +// You can also do conversion from non-supported data types if necessary - in +// this case, you ignore the input_ptr and just use the x and y parameters to +// calculate your own input_ptr based on the size of each non-supported pixel. +// (Something like the third example below.) +// +// You can also install just an input or just an output callback by setting the +// callback that you don't want to zero. +// +// First example, progress: (getting a callback that you can monitor the progress): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// percentage_done = y / input_height; +// return input_ptr; // use buffer from call +// } +// +// Next example, copying: (copy from some other buffer or stream): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// CopyOrStreamData( optional_output, other_data_src, num_pixels * pixel_width_in_bytes ); +// return optional_output; // return the optional buffer that we filled +// } +// +// Third example, input another buffer without copying: (zero-copy from other buffer): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// void * pixels = ( (char*) other_image_base ) + ( y * other_image_stride ) + ( x * other_pixel_width_in_bytes ); +// return pixels; // return pointer to your data without copying +// } +// +// +// The output callback is considerably simpler - it just calls you so that you can dump +// out each scanline. You could even directly copy out to disk if you have a simple format +// like TGA or BMP. You can also convert to other output types here if you want. +// +// Simple example: +// void const * my_output( void * output_ptr, int num_pixels, int y, void * context ) +// { +// percentage_done = y / output_height; +// fwrite( output_ptr, pixel_width_in_bytes, num_pixels, output_file ); +// } +//=============================================================== + + + + +//=============================================================== +// optional built-in profiling API +//-------------------------------- + +#ifdef STBIR_PROFILE + +typedef struct STBIR_PROFILE_INFO +{ + stbir_uint64 total_clocks; + + // how many clocks spent (of total_clocks) in the various resize routines, along with a string description + // there are "resize_count" number of zones + stbir_uint64 clocks[ 8 ]; + char const ** descriptions; + + // count of clocks and descriptions + stbir_uint32 count; +} STBIR_PROFILE_INFO; + +// use after calling stbir_resize_extended (or stbir_build_samplers or stbir_build_samplers_with_splits) +STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize ); + +// use after calling stbir_resize_extended +STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize ); + +// use after calling stbir_resize_extended_split +STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize, int split_start, int split_num ); + +//=============================================================== + +#endif + + +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE2_H + +#if defined(STB_IMAGE_RESIZE_IMPLEMENTATION) || defined(STB_IMAGE_RESIZE2_IMPLEMENTATION) + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +#ifndef STBIR_MALLOC +#include +#define STBIR_MALLOC(size,user_data) ((void)(user_data), malloc(size)) +#define STBIR_FREE(ptr,user_data) ((void)(user_data), free(ptr)) +// (we used the comma operator to evaluate user_data, to avoid "unused parameter" warnings) +#endif + +#ifdef _MSC_VER + +#define stbir__inline __forceinline + +#else + +#define stbir__inline __inline__ + +// Clang address sanitizer +#if defined(__has_feature) + #if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer) + #ifndef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__SEPARATE_ALLOCATIONS + #endif + #endif +#endif + +#endif + +// GCC and MSVC +#if defined(__SANITIZE_ADDRESS__) + #ifndef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__SEPARATE_ALLOCATIONS + #endif +#endif + +// Always turn off automatic FMA use - use STBIR_USE_FMA if you want. +// Otherwise, this is a determinism disaster. +#ifndef STBIR_DONT_CHANGE_FP_CONTRACT // override in case you don't want this behavior +#if defined(_MSC_VER) && !defined(__clang__) +#if _MSC_VER > 1200 +#pragma fp_contract(off) +#endif +#elif defined(__GNUC__) && !defined(__clang__) +#pragma GCC optimize("fp-contract=off") +#else +#pragma STDC FP_CONTRACT OFF +#endif +#endif + +#ifdef _MSC_VER +#define STBIR__UNUSED(v) (void)(v) +#else +#define STBIR__UNUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + + +#ifndef STBIR__HEADER_FILENAME +#define STBIR__HEADER_FILENAME "stb_image_resize2.h" +#endif + +// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +typedef enum +{ + STBIRI_1CHANNEL = 0, + STBIRI_2CHANNEL = 1, + STBIRI_RGB = 2, + STBIRI_BGR = 3, + STBIRI_4CHANNEL = 4, + + STBIRI_RGBA = 5, + STBIRI_BGRA = 6, + STBIRI_ARGB = 7, + STBIRI_ABGR = 8, + STBIRI_RA = 9, + STBIRI_AR = 10, + + STBIRI_RGBA_PM = 11, + STBIRI_BGRA_PM = 12, + STBIRI_ARGB_PM = 13, + STBIRI_ABGR_PM = 14, + STBIRI_RA_PM = 15, + STBIRI_AR_PM = 16, +} stbir_internal_pixel_layout; + +// define the public pixel layouts to not compile inside the implementation (to avoid accidental use) +#define STBIR_BGR bad_dont_use_in_implementation +#define STBIR_1CHANNEL STBIR_BGR +#define STBIR_2CHANNEL STBIR_BGR +#define STBIR_RGB STBIR_BGR +#define STBIR_RGBA STBIR_BGR +#define STBIR_4CHANNEL STBIR_BGR +#define STBIR_BGRA STBIR_BGR +#define STBIR_ARGB STBIR_BGR +#define STBIR_ABGR STBIR_BGR +#define STBIR_RA STBIR_BGR +#define STBIR_AR STBIR_BGR +#define STBIR_RGBA_PM STBIR_BGR +#define STBIR_BGRA_PM STBIR_BGR +#define STBIR_ARGB_PM STBIR_BGR +#define STBIR_ABGR_PM STBIR_BGR +#define STBIR_RA_PM STBIR_BGR +#define STBIR_AR_PM STBIR_BGR + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1,1,1,2,4,2 // STBIR_TYPE_UINT8,STBIR_TYPE_UINT8_SRGB,STBIR_TYPE_UINT8_SRGB_ALPHA,STBIR_TYPE_UINT16,STBIR_TYPE_FLOAT,STBIR_TYPE_HALF_FLOAT +}; + +// When gathering, the contributors are which source pixels contribute. +// When scattering, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + int lowest; // First sample index for whole filter + int highest; // Last sample index for whole filter + int widest; // widest single set of samples for an output +} stbir__filter_extent_info; + +typedef struct +{ + int n0; // First pixel of decode buffer to write to + int n1; // Last pixel of decode that will be written to + int pixel_offset_for_input; // Pixel offset into input_scanline +} stbir__span; + +typedef struct stbir__scale_info +{ + int input_full_size; + int output_sub_size; + float scale; + float inv_scale; + float pixel_shift; // starting shift in output pixel space (in pixels) + int scale_is_rational; + stbir_uint32 scale_numerator, scale_denominator; +} stbir__scale_info; + +typedef struct +{ + stbir__contributors * contributors; + float* coefficients; + stbir__contributors * gather_prescatter_contributors; + float * gather_prescatter_coefficients; + stbir__scale_info scale_info; + float support; + stbir_filter filter_enum; + stbir__kernel_callback * filter_kernel; + stbir__support_callback * filter_support; + stbir_edge edge; + int coefficient_width; + int filter_pixel_width; + int filter_pixel_margin; + int num_contributors; + int contributors_size; + int coefficients_size; + stbir__filter_extent_info extent_info; + int is_gather; // 0 = scatter, 1 = gather with scale >= 1, 2 = gather with scale < 1 + int gather_prescatter_num_contributors; + int gather_prescatter_coefficient_width; + int gather_prescatter_contributors_size; + int gather_prescatter_coefficients_size; +} stbir__sampler; + +typedef struct +{ + stbir__contributors conservative; + int edge_sizes[2]; // this can be less than filter_pixel_margin, if the filter and scaling falls off + stbir__span spans[2]; // can be two spans, if doing input subrect with clamp mode WRAP +} stbir__extents; + +typedef struct +{ +#ifdef STBIR_PROFILE + union + { + struct { stbir_uint64 total, looping, vertical, horizontal, decode, encode, alpha, unalpha; } named; + stbir_uint64 array[8]; + } profile; + stbir_uint64 * current_zone_excluded_ptr; +#endif + float* decode_buffer; + + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + int start_output_y, end_output_y; + int start_input_y, end_input_y; // used in scatter only + + #ifdef STBIR__SEPARATE_ALLOCATIONS + float** ring_buffers; // one pointer for each ring buffer + #else + float* ring_buffer; // one big buffer that we index into + #endif + + float* vertical_buffer; + + char no_cache_straddle[64]; +} stbir__per_split_info; + +typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input ); +typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels ); +typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, + stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ); +typedef void stbir__alpha_unweight_func(float * encode_buffer, int width_times_channels ); +typedef void stbir__encode_pixels_func( void * output, int width_times_channels, float const * encode ); + +struct stbir__info +{ +#ifdef STBIR_PROFILE + union + { + struct { stbir_uint64 total, build, alloc, horizontal, vertical, cleanup, pivot; } named; + stbir_uint64 array[7]; + } profile; + stbir_uint64 * current_zone_excluded_ptr; +#endif + stbir__sampler horizontal; + stbir__sampler vertical; + + void const * input_data; + void * output_data; + + int input_stride_bytes; + int output_stride_bytes; + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + + stbir_datatype input_type; + stbir_datatype output_type; + + stbir_input_callback * in_pixels_cb; + void * user_data; + stbir_output_callback * out_pixels_cb; + + stbir__extents scanline_extents; + + void * alloced_mem; + stbir__per_split_info * split_info; // by default 1, but there will be N of these allocated based on the thread init you did + + stbir__decode_pixels_func * decode_pixels; + stbir__alpha_weight_func * alpha_weight; + stbir__horizontal_gather_channels_func * horizontal_gather_channels; + stbir__alpha_unweight_func * alpha_unweight; + stbir__encode_pixels_func * encode_pixels; + + int alloc_ring_buffer_num_entries; // Number of entries in the ring buffer that will be allocated + int splits; // count of splits + + stbir_internal_pixel_layout input_pixel_layout_internal; + stbir_internal_pixel_layout output_pixel_layout_internal; + + int input_color_and_type; + int offset_x, offset_y; // offset within output_data + int vertical_first; + int channels; + int effective_channels; // same as channels, except on RGBA/ARGB (7), or XA/AX (3) + size_t alloced_total; +}; + + +#define stbir__max_uint8_as_float 255.0f +#define stbir__max_uint16_as_float 65535.0f +#define stbir__max_uint8_as_float_inverted (1.0f/255.0f) +#define stbir__max_uint16_as_float_inverted (1.0f/65535.0f) +#define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) + +// min/max friendly +#define STBIR_CLAMP(x, xmin, xmax) for(;;) { \ + if ( (x) < (xmin) ) (x) = (xmin); \ + if ( (x) > (xmax) ) (x) = (xmax); \ + break; \ +} + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline int stbir__max(int a, int b) +{ + return a > b ? a : b; +} + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +typedef union +{ + unsigned int u; + float f; +} stbir__FP32; + +// From https://gist.github.com/rygorous/2203834 + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + return 0; + if (in > almostone.f) + return 255; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#ifndef STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT +#define STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT 32 // when downsampling and <= 32 scanlines of buffering, use gather. gather used down to 1/8th scaling for 25% win. +#endif + +#ifndef STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS +#define STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS 4 // when threading, what is the minimum number of scanlines for a split? +#endif + +// restrict pointers for the output pointers, other loop and unroll control +#if defined( _MSC_VER ) && !defined(__clang__) + #define STBIR_STREAMOUT_PTR( star ) star __restrict + #define STBIR_NO_UNROLL( ptr ) __assume(ptr) // this oddly keeps msvc from unrolling a loop + #if _MSC_VER >= 1900 + #define STBIR_NO_UNROLL_LOOP_START __pragma(loop( no_vector )) + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif +#elif defined( __clang__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) + #if ( __clang_major__ >= 4 ) || ( ( __clang_major__ >= 3 ) && ( __clang_minor__ >= 5 ) ) + #define STBIR_NO_UNROLL_LOOP_START _Pragma("clang loop unroll(disable)") _Pragma("clang loop vectorize(disable)") + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif +#elif defined( __GNUC__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) + #if __GNUC__ >= 14 + #define STBIR_NO_UNROLL_LOOP_START _Pragma("GCC unroll 0") _Pragma("GCC novector") + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif + #define STBIR_NO_UNROLL_LOOP_START_INF_FOR +#else + #define STBIR_STREAMOUT_PTR( star ) star + #define STBIR_NO_UNROLL( ptr ) + #define STBIR_NO_UNROLL_LOOP_START +#endif + +#ifndef STBIR_NO_UNROLL_LOOP_START_INF_FOR +#define STBIR_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START +#endif + +#ifdef STBIR_NO_SIMD // force simd off for whatever reason + +// force simd off overrides everything else, so clear it all + +#ifdef STBIR_SSE2 +#undef STBIR_SSE2 +#endif + +#ifdef STBIR_AVX +#undef STBIR_AVX +#endif + +#ifdef STBIR_NEON +#undef STBIR_NEON +#endif + +#ifdef STBIR_AVX2 +#undef STBIR_AVX2 +#endif + +#ifdef STBIR_FP16C +#undef STBIR_FP16C +#endif + +#ifdef STBIR_WASM +#undef STBIR_WASM +#endif + +#ifdef STBIR_SIMD +#undef STBIR_SIMD +#endif + +#else // STBIR_SIMD + +#ifdef STBIR_SSE2 + #include + + #define stbir__simdf __m128 + #define stbir__simdi __m128i + + #define stbir_simdi_castf( reg ) _mm_castps_si128(reg) + #define stbir_simdf_casti( reg ) _mm_castsi128_ps(reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = _mm_loadu_ps( (float const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = _mm_loadu_si128 ( (stbir__simdi const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = _mm_castps_si128( _mm_load_ss( (float const*)(ptr) )) + #define stbir__simdf_load1z( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) ) // top values must be zero + #define stbir__simdf_frep4( fvar ) _mm_set_ps1( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = _mm_set_ps1( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = _mm_castpd_ps(_mm_loadh_pd( _mm_castps_pd(reg), (double*)(ptr) )) + + #define stbir__simdf_zeroP() _mm_setzero_ps() + #define stbir__simdf_zero( reg ) (reg) = _mm_setzero_ps() + + #define stbir__simdf_store( ptr, reg ) _mm_storeu_ps( (float*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), reg ) + #define stbir__simdf_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), _mm_castps_si128(reg) ) + #define stbir__simdf_store2h( ptr, reg ) _mm_storeh_pd( (double*)(ptr), _mm_castps_pd(reg) ) + + #define stbir__simdi_store( ptr, reg ) _mm_storeu_si128( (__m128i*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), _mm_castsi128_ps(reg) ) + #define stbir__simdi_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), (reg) ) + + #define stbir__prefetch( ptr ) _mm_prefetch((char*)(ptr), _MM_HINT_T0 ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out2 = _mm_unpacklo_epi8( ireg, zero ); \ + out3 = _mm_unpackhi_epi8( ireg, zero ); \ + out0 = _mm_unpacklo_epi16( out2, zero ); \ + out1 = _mm_unpackhi_epi16( out2, zero ); \ + out2 = _mm_unpacklo_epi16( out3, zero ); \ + out3 = _mm_unpackhi_epi16( out3, zero ); \ + } + +#define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out = _mm_unpacklo_epi8( ireg, zero ); \ + out = _mm_unpacklo_epi16( out, zero ); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out0 = _mm_unpacklo_epi16( ireg, zero ); \ + out1 = _mm_unpackhi_epi16( ireg, zero ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = _mm_cvttps_epi32(f) + #define stbir__simdf_convert_float_to_int( f ) _mm_cvtt_ss2si(f) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),_mm_setzero_ps())))) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())))) + + #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = _mm_cvtepi32_ps( ireg ) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = _mm_add_ps( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = _mm_mul_ps( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = _mm_mul_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = _mm_mul_ss( reg, _mm_load_ss( (float const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = _mm_add_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = _mm_add_ss( reg, _mm_load_ss( (float const*)(ptr) ) ) + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd + #include + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_fmadd_ps( mul1, mul2, add ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_fmadd_ss( mul1, mul2, add ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ps( mul, _mm_loadu_ps( (float const*)(ptr) ), add ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ss( mul, _mm_load_ss( (float const*)(ptr) ), add ) + #else + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_add_ps( add, _mm_mul_ps( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_add_ss( add, _mm_mul_ss( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_add_ps( add, _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_add_ss( add, _mm_mul_ss( mul, _mm_load_ss( (float const*)(ptr) ) ) ) + #endif + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = _mm_add_ss( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = _mm_mul_ss( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = _mm_and_ps( reg0, reg1 ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = _mm_or_ps( reg0, reg1 ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = _mm_min_ps( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = _mm_max_ps( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = _mm_min_ss( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = _mm_max_ss( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (3<<0) + (0<<2) + (1<<4) + (2<<6) ) ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (2<<0) + (3<<2) + (0<<4) + (1<<6) ) ) + + static const stbir__simdf STBIR_zeroones = { 0.0f,1.0f,0.0f,1.0f }; + static const stbir__simdf STBIR_onezeros = { 1.0f,0.0f,1.0f,0.0f }; + #define stbir__simdf_aaa1( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movehl_ps( ones, alp ) ), (1<<0) + (1<<2) + (1<<4) + (2<<6) ) ) + #define stbir__simdf_1aaa( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movelh_ps( ones, alp ) ), (0<<0) + (2<<2) + (2<<4) + (2<<6) ) ) + #define stbir__simdf_a1a1( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_srli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_zeroones ) + #define stbir__simdf_1a1a( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_slli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_onezeros ) + + #define stbir__simdf_swiz( reg, one, two, three, four ) _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( reg ), (one<<0) + (two<<2) + (three<<4) + (four<<6) ) ) + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = _mm_and_si128( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = _mm_or_si128( reg0, reg1 ) + #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = _mm_madd_epi16( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + stbir__simdf af,bf; \ + stbir__simdi a,b; \ + af = _mm_min_ps( aa, STBIR_max_uint8_as_float ); \ + bf = _mm_min_ps( bb, STBIR_max_uint8_as_float ); \ + af = _mm_max_ps( af, _mm_setzero_ps() ); \ + bf = _mm_max_ps( bf, _mm_setzero_ps() ); \ + a = _mm_cvttps_epi32( af ); \ + b = _mm_cvttps_epi32( bf ); \ + a = _mm_packs_epi32( a, b ); \ + out = _mm_packus_epi16( a, a ); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + stbir__simdf_load( o0, (ptr) ); \ + stbir__simdf_load( o1, (ptr)+4 ); \ + stbir__simdf_load( o2, (ptr)+8 ); \ + stbir__simdf_load( o3, (ptr)+12 ); \ + { \ + __m128 tmp0, tmp1, tmp2, tmp3; \ + tmp0 = _mm_unpacklo_ps(o0, o1); \ + tmp2 = _mm_unpacklo_ps(o2, o3); \ + tmp1 = _mm_unpackhi_ps(o0, o1); \ + tmp3 = _mm_unpackhi_ps(o2, o3); \ + o0 = _mm_movelh_ps(tmp0, tmp2); \ + o1 = _mm_movehl_ps(tmp2, tmp0); \ + o2 = _mm_movelh_ps(tmp1, tmp3); \ + o3 = _mm_movehl_ps(tmp3, tmp1); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + r0 = _mm_packs_epi32( r0, r1 ); \ + r2 = _mm_packs_epi32( r2, r3 ); \ + r1 = _mm_unpacklo_epi16( r0, r2 ); \ + r3 = _mm_unpackhi_epi16( r0, r2 ); \ + r0 = _mm_unpacklo_epi16( r1, r3 ); \ + r2 = _mm_unpackhi_epi16( r1, r3 ); \ + r0 = _mm_packus_epi16( r0, r2 ); \ + stbir__simdi_store( ptr, r0 ); \ + + #define stbir__simdi_32shr( out, reg, imm ) out = _mm_srli_epi32( reg, imm ) + + #if defined(_MSC_VER) && !defined(__clang__) + // msvc inits with 8 bytes + #define STBIR__CONST_32_TO_8( v ) (char)(unsigned char)((v)&255),(char)(unsigned char)(((v)>>8)&255),(char)(unsigned char)(((v)>>16)&255),(char)(unsigned char)(((v)>>24)&255) + #define STBIR__CONST_4_32i( v ) STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ) + #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) STBIR__CONST_32_TO_8( v0 ), STBIR__CONST_32_TO_8( v1 ), STBIR__CONST_32_TO_8( v2 ), STBIR__CONST_32_TO_8( v3 ) + #else + // everything else inits with long long's + #define STBIR__CONST_4_32i( v ) (long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))),(long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))) + #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) (long long)((((stbir_uint64)(stbir_uint32)(v1))<<32)|((stbir_uint64)(stbir_uint32)(v0))),(long long)((((stbir_uint64)(stbir_uint32)(v3))<<32)|((stbir_uint64)(stbir_uint32)(v2))) + #endif + + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { STBIR__CONST_4_32i(x) } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + + #if defined(STBIR_AVX) || defined(__SSE4_1__) + #include + #define stbir__simdf_pack_to_8words(out,reg0,reg1) out = _mm_packus_epi32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())), _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps()))) + #else + STBIRDEF STBIR__SIMDI_CONST(stbir__s32_32768, 32768); + STBIRDEF STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768)); + + #define stbir__simdf_pack_to_8words(out,reg0,reg1) \ + { \ + stbir__simdi tmp0,tmp1; \ + tmp0 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \ + tmp1 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \ + tmp0 = _mm_sub_epi32( tmp0, stbir__s32_32768 ); \ + tmp1 = _mm_sub_epi32( tmp1, stbir__s32_32768 ); \ + out = _mm_packs_epi32( tmp0, tmp1 ); \ + out = _mm_sub_epi16( out, stbir__s16_32768 ); \ + } + + #endif + + #define STBIR_SIMD + + // if we detect AVX, set the simd8 defines + #ifdef STBIR_AVX + #include + #define STBIR_SIMD8 + #define stbir__simdf8 __m256 + #define stbir__simdi8 __m256i + #define stbir__simdf8_load( out, ptr ) (out) = _mm256_loadu_ps( (float const *)(ptr) ) + #define stbir__simdi8_load( out, ptr ) (out) = _mm256_loadu_si256( (__m256i const *)(ptr) ) + #define stbir__simdf8_mult( out, a, b ) (out) = _mm256_mul_ps( (a), (b) ) + #define stbir__simdf8_store( ptr, out ) _mm256_storeu_ps( (float*)(ptr), out ) + #define stbir__simdi8_store( ptr, reg ) _mm256_storeu_si256( (__m256i*)(ptr), reg ) + #define stbir__simdf8_frep8( fval ) _mm256_set1_ps( fval ) + + #define stbir__simdf8_min( out, reg0, reg1 ) (out) = _mm256_min_ps( reg0, reg1 ) + #define stbir__simdf8_max( out, reg0, reg1 ) (out) = _mm256_max_ps( reg0, reg1 ) + + #define stbir__simdf8_add4halves( out, bot4, top8 ) (out) = _mm_add_ps( bot4, _mm256_extractf128_ps( top8, 1 ) ) + #define stbir__simdf8_mult_mem( out, reg, ptr ) (out) = _mm256_mul_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf8_add_mem( out, reg, ptr ) (out) = _mm256_add_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf8_add( out, a, b ) (out) = _mm256_add_ps( a, b ) + #define stbir__simdf8_load1b( out, ptr ) (out) = _mm256_broadcast_ss( ptr ) + #define stbir__simdf_load1rep4( out, ptr ) (out) = _mm_broadcast_ss( ptr ) // avx load instruction + + #define stbir__simdi8_convert_i32_to_float(out, ireg) (out) = _mm256_cvtepi32_ps( ireg ) + #define stbir__simdf8_convert_float_to_i32( i, f ) (i) = _mm256_cvttps_epi32(f) + + #define stbir__simdf8_bot4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (0<<0)+(2<<4) ) + #define stbir__simdf8_top4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (1<<0)+(3<<4) ) + + #define stbir__simdf8_gettop4( reg ) _mm256_extractf128_ps(reg,1) + + #ifdef STBIR_AVX2 + + #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi8 a, zero =_mm256_setzero_si256();\ + a = _mm256_permute4x64_epi64( _mm256_unpacklo_epi8( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), zero ),(0<<0)+(2<<2)+(1<<4)+(3<<6)); \ + out0 = _mm256_unpacklo_epi16( a, zero ); \ + out1 = _mm256_unpackhi_epi16( a, zero ); \ + } + + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ + { \ + stbir__simdi8 t; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + t = _mm256_permute4x64_epi64( _mm256_packs_epi32( a, b ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \ + out = _mm256_castsi256_si128( _mm256_permute4x64_epi64( _mm256_packus_epi16( t, t ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ) ); \ + } + + #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() ); + + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ + { \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + (out) = _mm256_permute4x64_epi64( _mm256_packus_epi32(a, b), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \ + } + + #else + + #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi a,zero = _mm_setzero_si128(); \ + a = _mm_unpacklo_epi8( ireg, zero ); \ + out0 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ + a = _mm_unpackhi_epi8( ireg, zero ); \ + out1 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ + } + + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ + { \ + stbir__simdi t; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + out = _mm_packs_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \ + out = _mm_packus_epi16( out, out ); \ + t = _mm_packs_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \ + t = _mm_packus_epi16( t, t ); \ + out = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps(out), _mm_castsi128_ps(t), (0<<0)+(1<<2)+(0<<4)+(1<<6) ) ); \ + } + + #define stbir__simdi8_expand_u16_to_u32(out,ireg) \ + { \ + stbir__simdi a,b,zero = _mm_setzero_si128(); \ + a = _mm_unpacklo_epi16( ireg, zero ); \ + b = _mm_unpackhi_epi16( ireg, zero ); \ + out = _mm256_insertf128_si256( _mm256_castsi128_si256( a ), b, 1 ); \ + } + + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ + { \ + stbir__simdi t0,t1; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + t0 = _mm_packus_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \ + t1 = _mm_packus_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \ + out = _mm256_setr_m128i( t0, t1 ); \ + } + + #endif + + static __m256i stbir_00001111 = { STBIR__CONST_4d_32i( 0, 0, 0, 0 ), STBIR__CONST_4d_32i( 1, 1, 1, 1 ) }; + #define stbir__simdf8_0123to00001111( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00001111 ) + + static __m256i stbir_22223333 = { STBIR__CONST_4d_32i( 2, 2, 2, 2 ), STBIR__CONST_4d_32i( 3, 3, 3, 3 ) }; + #define stbir__simdf8_0123to22223333( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_22223333 ) + + #define stbir__simdf8_0123to2222( out, in ) (out) = stbir__simdf_swiz(_mm256_castps256_ps128(in), 2,2,2,2 ) + + #define stbir__simdf8_load4b( out, ptr ) (out) = _mm256_broadcast_ps( (__m128 const *)(ptr) ) + + static __m256i stbir_00112233 = { STBIR__CONST_4d_32i( 0, 0, 1, 1 ), STBIR__CONST_4d_32i( 2, 2, 3, 3 ) }; + #define stbir__simdf8_0123to00112233( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00112233 ) + #define stbir__simdf8_add4( out, a8, b ) (out) = _mm256_add_ps( a8, _mm256_castps128_ps256( b ) ) + + static __m256i stbir_load6 = { STBIR__CONST_4_32i( 0x80000000 ), STBIR__CONST_4d_32i( 0x80000000, 0x80000000, 0, 0 ) }; + #define stbir__simdf8_load6z( out, ptr ) (out) = _mm256_maskload_ps( ptr, stbir_load6 ) + + #define stbir__simdf8_0123to00000000( out, in ) (out) = _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(0<<4)+(0<<6) ) + #define stbir__simdf8_0123to11111111( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(1<<4)+(1<<6) ) + #define stbir__simdf8_0123to22222222( out, in ) (out) = _mm256_shuffle_ps ( in, in, (2<<0)+(2<<2)+(2<<4)+(2<<6) ) + #define stbir__simdf8_0123to33333333( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(3<<2)+(3<<4)+(3<<6) ) + #define stbir__simdf8_0123to21032103( out, in ) (out) = _mm256_shuffle_ps ( in, in, (2<<0)+(1<<2)+(0<<4)+(3<<6) ) + #define stbir__simdf8_0123to32103210( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(2<<2)+(1<<4)+(0<<6) ) + #define stbir__simdf8_0123to12301230( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(2<<2)+(3<<4)+(0<<6) ) + #define stbir__simdf8_0123to10321032( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(0<<2)+(3<<4)+(2<<6) ) + #define stbir__simdf8_0123to30123012( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(0<<2)+(1<<4)+(2<<6) ) + + #define stbir__simdf8_0123to11331133( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(3<<4)+(3<<6) ) + #define stbir__simdf8_0123to00220022( out, in ) (out) = _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(2<<4)+(2<<6) ) + + #define stbir__simdf8_aaa1( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(1<<1)+(1<<2)+(0<<3)+(1<<4)+(1<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (3<<0) + (3<<2) + (3<<4) + (0<<6) ) + #define stbir__simdf8_1aaa( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(1<<2)+(1<<3)+(0<<4)+(1<<5)+(1<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (0<<4) + (0<<6) ) + #define stbir__simdf8_a1a1( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(0<<1)+(1<<2)+(0<<3)+(1<<4)+(0<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) ) + #define stbir__simdf8_1a1a( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(0<<2)+(1<<3)+(0<<4)+(1<<5)+(0<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) ) + + #define stbir__simdf8_zero( reg ) (reg) = _mm256_setzero_ps() + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd + #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_fmadd_ps( mul1, mul2, add ) + #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ), add ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr )(out) = _mm256_fmadd_ps( _mm256_setr_m128( mul, _mm_setzero_ps() ), _mm256_setr_m128( _mm_loadu_ps( (float const*)(ptr) ), _mm_setzero_ps() ), add ) + #else + #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul1, mul2 ) ) + #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ) ) ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_setr_m128( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ), _mm_setzero_ps() ) ) + #endif + #define stbir__if_simdf8_cast_to_simdf4( val ) _mm256_castps256_ps128( val ) + + #endif + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) // martins floorf + { + #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41) + __m128 t = _mm_set_ss(x); + return _mm_cvtss_f32( _mm_floor_ss(t, t) ); + #else + __m128 f = _mm_set_ss(x); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(f, t), _mm_set_ss(-1.0f))); + return _mm_cvtss_f32(r); + #endif + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) // martins ceilf + { + #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41) + __m128 t = _mm_set_ss(x); + return _mm_cvtss_f32( _mm_ceil_ss(t, t) ); + #else + __m128 f = _mm_set_ss(x); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(t, f), _mm_set_ss(1.0f))); + return _mm_cvtss_f32(r); + #endif + } + +#elif defined(STBIR_NEON) + + #include + + #define stbir__simdf float32x4_t + #define stbir__simdi uint32x4_t + + #define stbir_simdi_castf( reg ) vreinterpretq_u32_f32(reg) + #define stbir_simdf_casti( reg ) vreinterpretq_f32_u32(reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = vld1q_f32( (float const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = vld1q_u32( (uint32_t const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = vld1q_dup_f32( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = vld1q_dup_u32( (uint32_t const*)(ptr) ) + #define stbir__simdf_load1z( out, ptr ) (out) = vld1q_lane_f32( (float const*)(ptr), vdupq_n_f32(0), 0 ) // top values must be zero + #define stbir__simdf_frep4( fvar ) vdupq_n_f32( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = vdupq_n_f32( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = vcombine_f32( vget_low_f32(reg), vld1_f32( (float const*)(ptr) ) ) + + #define stbir__simdf_zeroP() vdupq_n_f32(0) + #define stbir__simdf_zero( reg ) (reg) = vdupq_n_f32(0) + + #define stbir__simdf_store( ptr, reg ) vst1q_f32( (float*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) vst1q_lane_f32( (float*)(ptr), reg, 0) + #define stbir__simdf_store2( ptr, reg ) vst1_f32( (float*)(ptr), vget_low_f32(reg) ) + #define stbir__simdf_store2h( ptr, reg ) vst1_f32( (float*)(ptr), vget_high_f32(reg) ) + + #define stbir__simdi_store( ptr, reg ) vst1q_u32( (uint32_t*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) vst1q_lane_u32( (uint32_t*)(ptr), reg, 0 ) + #define stbir__simdi_store2( ptr, reg ) vst1_u32( (uint32_t*)(ptr), vget_low_u32(reg) ) + + #define stbir__prefetch( ptr ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + uint16x8_t l = vmovl_u8( vget_low_u8 ( vreinterpretq_u8_u32(ireg) ) ); \ + uint16x8_t h = vmovl_u8( vget_high_u8( vreinterpretq_u8_u32(ireg) ) ); \ + out0 = vmovl_u16( vget_low_u16 ( l ) ); \ + out1 = vmovl_u16( vget_high_u16( l ) ); \ + out2 = vmovl_u16( vget_low_u16 ( h ) ); \ + out3 = vmovl_u16( vget_high_u16( h ) ); \ + } + + #define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + uint16x8_t tmp = vmovl_u8( vget_low_u8( vreinterpretq_u8_u32(ireg) ) ); \ + out = vmovl_u16( vget_low_u16( tmp ) ); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + uint16x8_t tmp = vreinterpretq_u16_u32(ireg); \ + out0 = vmovl_u16( vget_low_u16 ( tmp ) ); \ + out1 = vmovl_u16( vget_high_u16( tmp ) ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = vreinterpretq_u32_s32( vcvtq_s32_f32(f) ) + #define stbir__simdf_convert_float_to_int( f ) vgetq_lane_s32(vcvtq_s32_f32(f), 0) + #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),vdupq_n_f32(0))), 0)) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),vdupq_n_f32(0))), 0)) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = vcvtq_f32_s32( vreinterpretq_s32_u32(ireg) ) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) ) + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd (and also x64 no madd to arm madd) + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_dup_f32( (float const*)(ptr) ) ) + #else + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_f32( (float const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_dup_f32( (float const*)(ptr) ) ) ) + #endif + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vandq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vorrq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 3 ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 2 ) + + #define stbir__simdf_a1a1( out, alp, ones ) (out) = vzipq_f32(vuzpq_f32(alp, alp).val[1], ones).val[0] + #define stbir__simdf_1a1a( out, alp, ones ) (out) = vzipq_f32(ones, vuzpq_f32(alp, alp).val[0]).val[0] + + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + + #define stbir__simdf_aaa1( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3, ones, 3) + #define stbir__simdf_1aaa( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0, ones, 0) + + #if defined( _MSC_VER ) && !defined(__clang__) + #define stbir_make16(a,b,c,d) vcombine_u8( \ + vcreate_u8( (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \ + ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56)), \ + vcreate_u8( (4*c+0) | ((4*c+1)<<8) | ((4*c+2)<<16) | ((4*c+3)<<24) | \ + ((stbir_uint64)(4*d+0)<<32) | ((stbir_uint64)(4*d+1)<<40) | ((stbir_uint64)(4*d+2)<<48) | ((stbir_uint64)(4*d+3)<<56) ) ) + + static stbir__inline uint8x16x2_t stbir_make16x2(float32x4_t rega,float32x4_t regb) + { + uint8x16x2_t r = { vreinterpretq_u8_f32(rega), vreinterpretq_u8_f32(regb) }; + return r; + } + #else + #define stbir_make16(a,b,c,d) (uint8x16_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3,4*c+0,4*c+1,4*c+2,4*c+3,4*d+0,4*d+1,4*d+2,4*d+3} + #define stbir_make16x2(a,b) (uint8x16x2_t){{vreinterpretq_u8_f32(a),vreinterpretq_u8_f32(b)}} + #endif + + #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vqtbl1q_u8( vreinterpretq_u8_f32(reg), stbir_make16(one, two, three, four) ) ) + #define stbir__simdf_swiz2( rega, regb, one, two, three, four ) vreinterpretq_f32_u8( vqtbl2q_u8( stbir_make16x2(rega,regb), stbir_make16(one, two, three, four) ) ) + + #define stbir__simdi_16madd( out, reg0, reg1 ) \ + { \ + int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ + int16x8_t r1 = vreinterpretq_s16_u32(reg1); \ + int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \ + int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \ + (out) = vreinterpretq_u32_s32( vpaddq_s32(tmp0, tmp1) ); \ + } + + #else + + #define stbir__simdf_aaa1( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3) + #define stbir__simdf_1aaa( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0) + + #if defined( _MSC_VER ) && !defined(__clang__) + static stbir__inline uint8x8x2_t stbir_make8x2(float32x4_t reg) + { + uint8x8x2_t r = { { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } }; + return r; + } + #define stbir_make8(a,b) vcreate_u8( \ + (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \ + ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56) ) + #else + #define stbir_make8x2(reg) (uint8x8x2_t){ { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } } + #define stbir_make8(a,b) (uint8x8_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3} + #endif + + #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vcombine_u8( \ + vtbl2_u8( stbir_make8x2( reg ), stbir_make8( one, two ) ), \ + vtbl2_u8( stbir_make8x2( reg ), stbir_make8( three, four ) ) ) ) + + #define stbir__simdi_16madd( out, reg0, reg1 ) \ + { \ + int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ + int16x8_t r1 = vreinterpretq_s16_u32(reg1); \ + int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \ + int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \ + int32x2_t out0 = vpadd_s32( vget_low_s32(tmp0), vget_high_s32(tmp0) ); \ + int32x2_t out1 = vpadd_s32( vget_low_s32(tmp1), vget_high_s32(tmp1) ); \ + (out) = vreinterpretq_u32_s32( vcombine_s32(out0, out1) ); \ + } + + #endif + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = vandq_u32( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = vorrq_u32( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \ + float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \ + int16x4_t ai = vqmovn_s32( vcvtq_s32_f32( af ) ); \ + int16x4_t bi = vqmovn_s32( vcvtq_s32_f32( bf ) ); \ + uint8x8_t out8 = vqmovun_s16( vcombine_s16(ai, bi) ); \ + out = vreinterpretq_u32_u8( vcombine_u8(out8, out8) ); \ + } + + #define stbir__simdf_pack_to_8words(out,aa,bb) \ + { \ + float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \ + float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \ + int32x4_t ai = vcvtq_s32_f32( af ); \ + int32x4_t bi = vcvtq_s32_f32( bf ); \ + out = vreinterpretq_u32_u16( vcombine_u16(vqmovun_s32(ai), vqmovun_s32(bi)) ); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + { \ + int16x4x2_t tmp0 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r0)), vqmovn_s32(vreinterpretq_s32_u32(r2)) ); \ + int16x4x2_t tmp1 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r1)), vqmovn_s32(vreinterpretq_s32_u32(r3)) ); \ + uint8x8x2_t out = \ + { { \ + vqmovun_s16( vcombine_s16(tmp0.val[0], tmp0.val[1]) ), \ + vqmovun_s16( vcombine_s16(tmp1.val[0], tmp1.val[1]) ), \ + } }; \ + vst2_u8(ptr, out); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + { \ + float32x4x4_t tmp = vld4q_f32(ptr); \ + o0 = tmp.val[0]; \ + o1 = tmp.val[1]; \ + o2 = tmp.val[2]; \ + o3 = tmp.val[3]; \ + } + + #define stbir__simdi_32shr( out, reg, imm ) out = vshrq_n_u32( reg, imm ) + + #if defined( _MSC_VER ) && !defined(__clang__) + #define STBIR__SIMDF_CONST(var, x) __declspec(align(8)) float var[] = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) __declspec(align(8)) uint32_t var[] = { x, x, x, x } + #define STBIR__CONSTF(var) (*(const float32x4_t*)var) + #define STBIR__CONSTI(var) (*(const uint32x4_t*)var) + #else + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + #endif + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) + { + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + return vget_lane_f32( vrndm_f32( vdup_n_f32(x) ), 0); + #else + float32x2_t f = vdup_n_f32(x); + float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f)); + uint32x2_t a = vclt_f32(f, t); + uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(-1.0f)); + float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b))); + return vget_lane_f32(r, 0); + #endif + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) + { + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + return vget_lane_f32( vrndp_f32( vdup_n_f32(x) ), 0); + #else + float32x2_t f = vdup_n_f32(x); + float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f)); + uint32x2_t a = vclt_f32(t, f); + uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(1.0f)); + float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b))); + return vget_lane_f32(r, 0); + #endif + } + + #define STBIR_SIMD + +#elif defined(STBIR_WASM) + + #include + + #define stbir__simdf v128_t + #define stbir__simdi v128_t + + #define stbir_simdi_castf( reg ) (reg) + #define stbir_simdf_casti( reg ) (reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = wasm_v128_load( (void const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = wasm_v128_load( (void const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = wasm_v128_load32_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = wasm_v128_load32_splat( (void const*)(ptr) ) + #define stbir__simdf_load1z( out, ptr ) (out) = wasm_v128_load32_zero( (void const*)(ptr) ) // top values must be zero + #define stbir__simdf_frep4( fvar ) wasm_f32x4_splat( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = wasm_f32x4_splat( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = wasm_v128_load64_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = wasm_v128_load64_zero( (void const*)(ptr) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = wasm_v128_load64_lane( (void const*)(ptr), reg, 1 ) + + #define stbir__simdf_zeroP() wasm_f32x4_const_splat(0) + #define stbir__simdf_zero( reg ) (reg) = wasm_f32x4_const_splat(0) + + #define stbir__simdf_store( ptr, reg ) wasm_v128_store( (void*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdf_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdf_store2h( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 1 ) + + #define stbir__simdi_store( ptr, reg ) wasm_v128_store( (void*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdi_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 ) + + #define stbir__prefetch( ptr ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + v128_t l = wasm_u16x8_extend_low_u8x16 ( ireg ); \ + v128_t h = wasm_u16x8_extend_high_u8x16( ireg ); \ + out0 = wasm_u32x4_extend_low_u16x8 ( l ); \ + out1 = wasm_u32x4_extend_high_u16x8( l ); \ + out2 = wasm_u32x4_extend_low_u16x8 ( h ); \ + out3 = wasm_u32x4_extend_high_u16x8( h ); \ + } + + #define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + v128_t tmp = wasm_u16x8_extend_low_u8x16(ireg); \ + out = wasm_u32x4_extend_low_u16x8(tmp); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + out0 = wasm_u32x4_extend_low_u16x8 ( ireg ); \ + out1 = wasm_u32x4_extend_high_u16x8( ireg ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = wasm_i32x4_trunc_sat_f32x4(f) + #define stbir__simdf_convert_float_to_int( f ) wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(f), 0) + #define stbir__simdi_to_int( i ) wasm_i32x4_extract_lane(i, 0) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint8_as_float),wasm_f32x4_const_splat(0))), 0)) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint16_as_float),wasm_f32x4_const_splat(0))), 0)) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = wasm_f32x4_convert_i32x4(ireg) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = wasm_f32x4_add( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = wasm_f32x4_mul( reg, wasm_v128_load( (void const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = wasm_f32x4_mul( reg, wasm_v128_load32_splat( (void const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = wasm_f32x4_add( reg, wasm_v128_load( (void const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = wasm_f32x4_add( reg, wasm_v128_load32_splat( (void const*)(ptr) ) ) + + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load( (void const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load32_splat( (void const*)(ptr) ) ) ) + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = wasm_f32x4_add( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = wasm_v128_or( reg0, reg1 ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 3, 4, 5, -1 ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 2, 3, 4, -1 ) + + #define stbir__simdf_aaa1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 3, 3, 3, 4) + #define stbir__simdf_1aaa(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 0, 0) + #define stbir__simdf_a1a1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 1, 4, 3, 4) + #define stbir__simdf_1a1a(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 4, 2) + + #define stbir__simdf_swiz( reg, one, two, three, four ) wasm_i32x4_shuffle(reg, reg, one, two, three, four) + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = wasm_v128_or( reg0, reg1 ) + #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = wasm_i32x4_dot_i16x8( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \ + v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \ + v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \ + v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \ + v128_t out16 = wasm_i16x8_narrow_i32x4( ai, bi ); \ + out = wasm_u8x16_narrow_i16x8( out16, out16 ); \ + } + + #define stbir__simdf_pack_to_8words(out,aa,bb) \ + { \ + v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \ + v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \ + v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \ + v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \ + out = wasm_u16x8_narrow_i32x4( ai, bi ); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + { \ + v128_t tmp0 = wasm_i16x8_narrow_i32x4(r0, r1); \ + v128_t tmp1 = wasm_i16x8_narrow_i32x4(r2, r3); \ + v128_t tmp = wasm_u8x16_narrow_i16x8(tmp0, tmp1); \ + tmp = wasm_i8x16_shuffle(tmp, tmp, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); \ + wasm_v128_store( (void*)(ptr), tmp); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + { \ + v128_t t0 = wasm_v128_load( ptr ); \ + v128_t t1 = wasm_v128_load( ptr+4 ); \ + v128_t t2 = wasm_v128_load( ptr+8 ); \ + v128_t t3 = wasm_v128_load( ptr+12 ); \ + v128_t s0 = wasm_i32x4_shuffle(t0, t1, 0, 4, 2, 6); \ + v128_t s1 = wasm_i32x4_shuffle(t0, t1, 1, 5, 3, 7); \ + v128_t s2 = wasm_i32x4_shuffle(t2, t3, 0, 4, 2, 6); \ + v128_t s3 = wasm_i32x4_shuffle(t2, t3, 1, 5, 3, 7); \ + o0 = wasm_i32x4_shuffle(s0, s2, 0, 1, 4, 5); \ + o1 = wasm_i32x4_shuffle(s1, s3, 0, 1, 4, 5); \ + o2 = wasm_i32x4_shuffle(s0, s2, 2, 3, 6, 7); \ + o3 = wasm_i32x4_shuffle(s1, s3, 2, 3, 6, 7); \ + } + + #define stbir__simdi_32shr( out, reg, imm ) out = wasm_u32x4_shr( reg, imm ) + + typedef float stbir__f32x4 __attribute__((__vector_size__(16), __aligned__(16))); + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = (v128_t)(stbir__f32x4){ x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) + { + return wasm_f32x4_extract_lane( wasm_f32x4_floor( wasm_f32x4_splat(x) ), 0); + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) + { + return wasm_f32x4_extract_lane( wasm_f32x4_ceil( wasm_f32x4_splat(x) ), 0); + } + + #define STBIR_SIMD + +#endif // SSE2/NEON/WASM + +#endif // NO SIMD + +#ifdef STBIR_SIMD8 + #define stbir__simdfX stbir__simdf8 + #define stbir__simdiX stbir__simdi8 + #define stbir__simdfX_load stbir__simdf8_load + #define stbir__simdiX_load stbir__simdi8_load + #define stbir__simdfX_mult stbir__simdf8_mult + #define stbir__simdfX_add_mem stbir__simdf8_add_mem + #define stbir__simdfX_madd_mem stbir__simdf8_madd_mem + #define stbir__simdfX_store stbir__simdf8_store + #define stbir__simdiX_store stbir__simdi8_store + #define stbir__simdf_frepX stbir__simdf8_frep8 + #define stbir__simdfX_madd stbir__simdf8_madd + #define stbir__simdfX_min stbir__simdf8_min + #define stbir__simdfX_max stbir__simdf8_max + #define stbir__simdfX_aaa1 stbir__simdf8_aaa1 + #define stbir__simdfX_1aaa stbir__simdf8_1aaa + #define stbir__simdfX_a1a1 stbir__simdf8_a1a1 + #define stbir__simdfX_1a1a stbir__simdf8_1a1a + #define stbir__simdfX_convert_float_to_i32 stbir__simdf8_convert_float_to_i32 + #define stbir__simdfX_pack_to_words stbir__simdf8_pack_to_16words + #define stbir__simdfX_zero stbir__simdf8_zero + #define STBIR_onesX STBIR_ones8 + #define STBIR_max_uint8_as_floatX STBIR_max_uint8_as_float8 + #define STBIR_max_uint16_as_floatX STBIR_max_uint16_as_float8 + #define STBIR_simd_point5X STBIR_simd_point58 + #define stbir__simdfX_float_count 8 + #define stbir__simdfX_0123to1230 stbir__simdf8_0123to12301230 + #define stbir__simdfX_0123to2103 stbir__simdf8_0123to21032103 + static const stbir__simdf8 STBIR_max_uint16_as_float_inverted8 = { stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted }; + static const stbir__simdf8 STBIR_max_uint8_as_float_inverted8 = { stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted }; + static const stbir__simdf8 STBIR_ones8 = { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }; + static const stbir__simdf8 STBIR_simd_point58 = { 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5 }; + static const stbir__simdf8 STBIR_max_uint8_as_float8 = { stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float, stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float }; + static const stbir__simdf8 STBIR_max_uint16_as_float8 = { stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float, stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float }; +#else + #define stbir__simdfX stbir__simdf + #define stbir__simdiX stbir__simdi + #define stbir__simdfX_load stbir__simdf_load + #define stbir__simdiX_load stbir__simdi_load + #define stbir__simdfX_mult stbir__simdf_mult + #define stbir__simdfX_add_mem stbir__simdf_add_mem + #define stbir__simdfX_madd_mem stbir__simdf_madd_mem + #define stbir__simdfX_store stbir__simdf_store + #define stbir__simdiX_store stbir__simdi_store + #define stbir__simdf_frepX stbir__simdf_frep4 + #define stbir__simdfX_madd stbir__simdf_madd + #define stbir__simdfX_min stbir__simdf_min + #define stbir__simdfX_max stbir__simdf_max + #define stbir__simdfX_aaa1 stbir__simdf_aaa1 + #define stbir__simdfX_1aaa stbir__simdf_1aaa + #define stbir__simdfX_a1a1 stbir__simdf_a1a1 + #define stbir__simdfX_1a1a stbir__simdf_1a1a + #define stbir__simdfX_convert_float_to_i32 stbir__simdf_convert_float_to_i32 + #define stbir__simdfX_pack_to_words stbir__simdf_pack_to_8words + #define stbir__simdfX_zero stbir__simdf_zero + #define STBIR_onesX STBIR__CONSTF(STBIR_ones) + #define STBIR_simd_point5X STBIR__CONSTF(STBIR_simd_point5) + #define STBIR_max_uint8_as_floatX STBIR__CONSTF(STBIR_max_uint8_as_float) + #define STBIR_max_uint16_as_floatX STBIR__CONSTF(STBIR_max_uint16_as_float) + #define stbir__simdfX_float_count 4 + #define stbir__if_simdf8_cast_to_simdf4( val ) ( val ) + #define stbir__simdfX_0123to1230 stbir__simdf_0123to1230 + #define stbir__simdfX_0123to2103 stbir__simdf_0123to2103 +#endif + + +#if defined(STBIR_NEON) && !defined(_M_ARM) && !defined(__arm__) + + #if defined( _MSC_VER ) && !defined(__clang__) + typedef __int16 stbir__FP16; + #else + typedef float16_t stbir__FP16; + #endif + +#else // no NEON, or 32-bit ARM for MSVC + + typedef union stbir__FP16 + { + unsigned short u; + } stbir__FP16; + +#endif + +#if (!defined(STBIR_NEON) && !defined(STBIR_FP16C)) || (defined(STBIR_NEON) && defined(_M_ARM)) || (defined(STBIR_NEON) && defined(__arm__)) + + // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + static const stbir__FP32 magic = { (254 - 15) << 23 }; + static const stbir__FP32 was_infnan = { (127 + 16) << 23 }; + stbir__FP32 o; + + o.u = (h.u & 0x7fff) << 13; // exponent/mantissa bits + o.f *= magic.f; // exponent adjust + if (o.f >= was_infnan.f) // make sure Inf/NaN survive + o.u |= 255 << 23; + o.u |= (h.u & 0x8000) << 16; // sign bit + return o.f; + } + + static stbir__inline stbir__FP16 stbir__float_to_half(float val) + { + stbir__FP32 f32infty = { 255 << 23 }; + stbir__FP32 f16max = { (127 + 16) << 23 }; + stbir__FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; + unsigned int sign_mask = 0x80000000u; + stbir__FP16 o = { 0 }; + stbir__FP32 f; + unsigned int sign; + + f.f = val; + sign = f.u & sign_mask; + f.u ^= sign; + + if (f.u >= f16max.u) // result is Inf or NaN (all exponent bits set) + o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf + else // (De)normalized number or zero + { + if (f.u < (113 << 23)) // resulting FP16 is subnormal or zero + { + // use a magic value to align our 10 mantissa bits at the bottom of + // the float. as long as FP addition is round-to-nearest-even this + // just works. + f.f += denorm_magic.f; + // and one integer subtract of the bias later, we have our final float! + o.u = (unsigned short) ( f.u - denorm_magic.u ); + } + else + { + unsigned int mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd + // update exponent, rounding bias part 1 + f.u = f.u + ((15u - 127) << 23) + 0xfff; + // rounding bias part 2 + f.u += mant_odd; + // take the bits! + o.u = (unsigned short) ( f.u >> 13 ); + } + } + + o.u |= sign >> 16; + return o; + } + +#endif + + +#if defined(STBIR_FP16C) + + #include + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + _mm256_storeu_ps( (float*)output, _mm256_cvtph_ps( _mm_loadu_si128( (__m128i const* )input ) ) ); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + _mm_storeu_si128( (__m128i*)output, _mm256_cvtps_ph( _mm256_loadu_ps( input ), 0 ) ); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return _mm_cvtss_f32( _mm_cvtph_ps( _mm_cvtsi32_si128( (int)h.u ) ) ); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + stbir__FP16 h; + h.u = (unsigned short) _mm_cvtsi128_si32( _mm_cvtps_ph( _mm_set_ss( f ), 0 ) ); + return h; + } + +#elif defined(STBIR_SSE2) + + // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 + stbir__inline static void stbir__half_to_float_SIMD(float * output, void const * input) + { + static const STBIR__SIMDI_CONST(mask_nosign, 0x7fff); + static const STBIR__SIMDI_CONST(smallest_normal, 0x0400); + static const STBIR__SIMDI_CONST(infinity, 0x7c00); + static const STBIR__SIMDI_CONST(expadjust_normal, (127 - 15) << 23); + static const STBIR__SIMDI_CONST(magic_denorm, 113 << 23); + + __m128i i = _mm_loadu_si128 ( (__m128i const*)(input) ); + __m128i h = _mm_unpacklo_epi16 ( i, _mm_setzero_si128() ); + __m128i mnosign = STBIR__CONSTI(mask_nosign); + __m128i eadjust = STBIR__CONSTI(expadjust_normal); + __m128i smallest = STBIR__CONSTI(smallest_normal); + __m128i infty = STBIR__CONSTI(infinity); + __m128i expmant = _mm_and_si128(mnosign, h); + __m128i justsign = _mm_xor_si128(h, expmant); + __m128i b_notinfnan = _mm_cmpgt_epi32(infty, expmant); + __m128i b_isdenorm = _mm_cmpgt_epi32(smallest, expmant); + __m128i shifted = _mm_slli_epi32(expmant, 13); + __m128i adj_infnan = _mm_andnot_si128(b_notinfnan, eadjust); + __m128i adjusted = _mm_add_epi32(eadjust, shifted); + __m128i den1 = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm)); + __m128i adjusted2 = _mm_add_epi32(adjusted, adj_infnan); + __m128 den2 = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm); + __m128 adjusted3 = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm)); + __m128 adjusted4 = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2)); + __m128 adjusted5 = _mm_or_ps(adjusted3, adjusted4); + __m128i sign = _mm_slli_epi32(justsign, 16); + __m128 final = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign)); + stbir__simdf_store( output + 0, final ); + + h = _mm_unpackhi_epi16 ( i, _mm_setzero_si128() ); + expmant = _mm_and_si128(mnosign, h); + justsign = _mm_xor_si128(h, expmant); + b_notinfnan = _mm_cmpgt_epi32(infty, expmant); + b_isdenorm = _mm_cmpgt_epi32(smallest, expmant); + shifted = _mm_slli_epi32(expmant, 13); + adj_infnan = _mm_andnot_si128(b_notinfnan, eadjust); + adjusted = _mm_add_epi32(eadjust, shifted); + den1 = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm)); + adjusted2 = _mm_add_epi32(adjusted, adj_infnan); + den2 = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm); + adjusted3 = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm)); + adjusted4 = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2)); + adjusted5 = _mm_or_ps(adjusted3, adjusted4); + sign = _mm_slli_epi32(justsign, 16); + final = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign)); + stbir__simdf_store( output + 4, final ); + + // ~38 SSE2 ops for 8 values + } + + // Fabian's round-to-nearest-even float to half + // ~48 SSE2 ops for 8 output + stbir__inline static void stbir__float_to_half_SIMD(void * output, float const * input) + { + static const STBIR__SIMDI_CONST(mask_sign, 0x80000000u); + static const STBIR__SIMDI_CONST(c_f16max, (127 + 16) << 23); // all FP32 values >=this round to +inf + static const STBIR__SIMDI_CONST(c_nanbit, 0x200); + static const STBIR__SIMDI_CONST(c_infty_as_fp16, 0x7c00); + static const STBIR__SIMDI_CONST(c_min_normal, (127 - 14) << 23); // smallest FP32 that yields a normalized FP16 + static const STBIR__SIMDI_CONST(c_subnorm_magic, ((127 - 15) + (23 - 10) + 1) << 23); + static const STBIR__SIMDI_CONST(c_normal_bias, 0xfff - ((127 - 15) << 23)); // adjust exponent and add mantissa rounding + + __m128 f = _mm_loadu_ps(input); + __m128 msign = _mm_castsi128_ps(STBIR__CONSTI(mask_sign)); + __m128 justsign = _mm_and_ps(msign, f); + __m128 absf = _mm_xor_ps(f, justsign); + __m128i absf_int = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit) + __m128i f16max = STBIR__CONSTI(c_f16max); + __m128 b_isnan = _mm_cmpunord_ps(absf, absf); // is this a NaN? + __m128i b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special? + __m128i nanbit = _mm_and_si128(_mm_castps_si128(b_isnan), STBIR__CONSTI(c_nanbit)); + __m128i inf_or_nan = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials + + __m128i min_normal = STBIR__CONSTI(c_min_normal); + __m128i b_issub = _mm_cmpgt_epi32(min_normal, absf_int); + + // "result is subnormal" path + __m128 subnorm1 = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa + __m128i subnorm2 = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias + + // "result is normal" path + __m128i mantoddbit = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign + __m128i mantodd = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0 + + __m128i round1 = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias)); + __m128i round2 = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE) + __m128i normal = _mm_srli_epi32(round2, 13); // rounded result + + // combine the two non-specials + __m128i nonspecial = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal)); + + // merge in specials as well + __m128i joined = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan)); + + __m128i sign_shift = _mm_srai_epi32(_mm_castps_si128(justsign), 16); + __m128i final2, final= _mm_or_si128(joined, sign_shift); + + f = _mm_loadu_ps(input+4); + justsign = _mm_and_ps(msign, f); + absf = _mm_xor_ps(f, justsign); + absf_int = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit) + b_isnan = _mm_cmpunord_ps(absf, absf); // is this a NaN? + b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special? + nanbit = _mm_and_si128(_mm_castps_si128(b_isnan), c_nanbit); + inf_or_nan = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials + + b_issub = _mm_cmpgt_epi32(min_normal, absf_int); + + // "result is subnormal" path + subnorm1 = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa + subnorm2 = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias + + // "result is normal" path + mantoddbit = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign + mantodd = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0 + + round1 = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias)); + round2 = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE) + normal = _mm_srli_epi32(round2, 13); // rounded result + + // combine the two non-specials + nonspecial = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal)); + + // merge in specials as well + joined = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan)); + + sign_shift = _mm_srai_epi32(_mm_castps_si128(justsign), 16); + final2 = _mm_or_si128(joined, sign_shift); + final = _mm_packs_epi32(final, final2); + stbir__simdi_store( output,final ); + } + +#elif defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) // 64-bit ARM on MSVC (not clang) + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + float16x4_t in0 = vld1_f16(input + 0); + float16x4_t in1 = vld1_f16(input + 4); + vst1q_f32(output + 0, vcvt_f32_f16(in0)); + vst1q_f32(output + 4, vcvt_f32_f16(in1)); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0)); + float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4)); + vst1_f16(output+0, out0); + vst1_f16(output+4, out1); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return vgetq_lane_f32(vcvt_f32_f16(vld1_dup_f16(&h)), 0); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0).n16_u16[0]; + } + +#elif defined(STBIR_NEON) && ( defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) ) // 64-bit ARM + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + float16x8_t in = vld1q_f16(input); + vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(in))); + vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(in))); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0)); + float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4)); + vst1q_f16(output, vcombine_f16(out0, out1)); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return vgetq_lane_f32(vcvt_f32_f16(vdup_n_f16(h)), 0); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0); + } + +#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && (defined(_MSC_VER) || defined(_M_ARM) || defined(__arm__))) // WASM or 32-bit ARM on MSVC/clang + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__half_to_float(input[i]); + } + } + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__float_to_half(input[i]); + } + } + +#endif + + +#ifdef STBIR_SIMD + +#define stbir__simdf_0123to3333( out, reg ) (out) = stbir__simdf_swiz( reg, 3,3,3,3 ) +#define stbir__simdf_0123to2222( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,2,2 ) +#define stbir__simdf_0123to1111( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,1,1 ) +#define stbir__simdf_0123to0000( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,0 ) +#define stbir__simdf_0123to0003( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,3 ) +#define stbir__simdf_0123to0001( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,1 ) +#define stbir__simdf_0123to1122( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,2,2 ) +#define stbir__simdf_0123to2333( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,3,3 ) +#define stbir__simdf_0123to0023( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,3 ) +#define stbir__simdf_0123to1230( out, reg ) (out) = stbir__simdf_swiz( reg, 1,2,3,0 ) +#define stbir__simdf_0123to2103( out, reg ) (out) = stbir__simdf_swiz( reg, 2,1,0,3 ) +#define stbir__simdf_0123to3210( out, reg ) (out) = stbir__simdf_swiz( reg, 3,2,1,0 ) +#define stbir__simdf_0123to2301( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,0,1 ) +#define stbir__simdf_0123to3012( out, reg ) (out) = stbir__simdf_swiz( reg, 3,0,1,2 ) +#define stbir__simdf_0123to0011( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,1,1 ) +#define stbir__simdf_0123to1100( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,0,0 ) +#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 ) +#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 ) +#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 ) +#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 ) + +typedef union stbir__simdi_u32 +{ + stbir_uint32 m128i_u32[4]; + int m128i_i32[4]; + stbir__simdi m128i_i128; +} stbir__simdi_u32; + +static const int STBIR_mask[9] = { 0,0,0,-1,-1,-1,0,0,0 }; + +static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float, stbir__max_uint8_as_float); +static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float, stbir__max_uint16_as_float); +static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float_inverted, stbir__max_uint8_as_float_inverted); +static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float_inverted, stbir__max_uint16_as_float_inverted); + +static const STBIR__SIMDF_CONST(STBIR_simd_point5, 0.5f); +static const STBIR__SIMDF_CONST(STBIR_ones, 1.0f); +static const STBIR__SIMDI_CONST(STBIR_almost_zero, (127 - 13) << 23); +static const STBIR__SIMDI_CONST(STBIR_almost_one, 0x3f7fffff); +static const STBIR__SIMDI_CONST(STBIR_mastissa_mask, 0xff); +static const STBIR__SIMDI_CONST(STBIR_topscale, 0x02000000); + +// Basically, in simd mode, we unroll the proper amount, and we don't want +// the non-simd remnant loops to be unroll because they only run a few times +// Adding this switch saves about 5K on clang which is Captain Unroll the 3rd. +#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) +#define STBIR_SIMD_NO_UNROLL(ptr) STBIR_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL_LOOP_START STBIR_NO_UNROLL_LOOP_START +#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START_INF_FOR + +#ifdef STBIR_MEMCPY +#undef STBIR_MEMCPY +#endif +#define STBIR_MEMCPY stbir_simd_memcpy + +// override normal use of memcpy with much simpler copy (faster and smaller with our sized copies) +static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) d = (char*) dest; + char STBIR_SIMD_STREAMOUT_PTR( * ) d_end = ((char*) dest) + bytes; + ptrdiff_t ofs_to_src = (char*)src - (char*)dest; + + // check overlaps + STBIR_ASSERT( ( ( d >= ( (char*)src) + bytes ) ) || ( ( d + bytes ) <= (char*)src ) ); + + if ( bytes < (16*stbir__simdfX_float_count) ) + { + if ( bytes < 16 ) + { + if ( bytes ) + { + STBIR_SIMD_NO_UNROLL_LOOP_START + do + { + STBIR_SIMD_NO_UNROLL(d); + d[ 0 ] = d[ ofs_to_src ]; + ++d; + } while ( d < d_end ); + } + } + else + { + stbir__simdf x; + // do one unaligned to get us aligned for the stream out below + stbir__simdf_load( x, ( d + ofs_to_src ) ); + stbir__simdf_store( d, x ); + d = (char*)( ( ( (size_t)d ) + 16 ) & ~15 ); + + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_SIMD_NO_UNROLL(d); + + if ( d > ( d_end - 16 ) ) + { + if ( d == d_end ) + return; + d = d_end - 16; + } + + stbir__simdf_load( x, ( d + ofs_to_src ) ); + stbir__simdf_store( d, x ); + d += 16; + } + } + } + else + { + stbir__simdfX x0,x1,x2,x3; + + // do one unaligned to get us aligned for the stream out below + stbir__simdfX_load( x0, ( d + ofs_to_src ) + 0*stbir__simdfX_float_count ); + stbir__simdfX_load( x1, ( d + ofs_to_src ) + 4*stbir__simdfX_float_count ); + stbir__simdfX_load( x2, ( d + ofs_to_src ) + 8*stbir__simdfX_float_count ); + stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count ); + stbir__simdfX_store( d + 0*stbir__simdfX_float_count, x0 ); + stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); + stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); + stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); + d = (char*)( ( ( (size_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) ); + + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_SIMD_NO_UNROLL(d); + + if ( d > ( d_end - (16*stbir__simdfX_float_count) ) ) + { + if ( d == d_end ) + return; + d = d_end - (16*stbir__simdfX_float_count); + } + + stbir__simdfX_load( x0, ( d + ofs_to_src ) + 0*stbir__simdfX_float_count ); + stbir__simdfX_load( x1, ( d + ofs_to_src ) + 4*stbir__simdfX_float_count ); + stbir__simdfX_load( x2, ( d + ofs_to_src ) + 8*stbir__simdfX_float_count ); + stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count ); + stbir__simdfX_store( d + 0*stbir__simdfX_float_count, x0 ); + stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); + stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); + stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); + d += (16*stbir__simdfX_float_count); + } + } +} + +// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be +// a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to +// the diff between dest and src) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; + ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; + + if ( ofs_to_dest >= 16 ) // is the overlap more than 16 away? + { + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end16 = ((char*) src) + (bytes&~15); + STBIR_SIMD_NO_UNROLL_LOOP_START + do + { + stbir__simdf x; + STBIR_SIMD_NO_UNROLL(sd); + stbir__simdf_load( x, sd ); + stbir__simdf_store( ( sd + ofs_to_dest ), x ); + sd += 16; + } while ( sd < s_end16 ); + + if ( sd == s_end ) + return; + } + + do + { + STBIR_SIMD_NO_UNROLL(sd); + *(int*)( sd + ofs_to_dest ) = *(int*) sd; + sd += 4; + } while ( sd < s_end ); +} + +#else // no SSE2 + +// when in scalar mode, we let unrolling happen, so this macro just does the __restrict +#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) +#define STBIR_SIMD_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL_LOOP_START +#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + +#endif // SSE2 + + +#ifdef STBIR_PROFILE + +#ifndef STBIR_PROFILE_FUNC + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) + +#ifdef _MSC_VER + + STBIRDEF stbir_uint64 __rdtsc(); + #define STBIR_PROFILE_FUNC() __rdtsc() + +#else // non msvc + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint32 lo, hi; + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) ); + return ( ( (stbir_uint64) hi ) << 32 ) | ( (stbir_uint64) lo ); + } + +#endif // msvc + +#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) + +#if defined( _MSC_VER ) && !defined(__clang__) + + #define STBIR_PROFILE_FUNC() _ReadStatusReg(ARM64_CNTVCT) + +#else + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint64 tsc; + asm volatile("mrs %0, cntvct_el0" : "=r" (tsc)); + return tsc; + } + +#endif + +#else // x64, arm + +#error Unknown platform for profiling. + +#endif // x64, arm + +#endif // STBIR_PROFILE_FUNC + +#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO ,stbir__per_split_info * split_info +#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO ,split_info + +#define STBIR_ONLY_PROFILE_BUILD_GET_INFO ,stbir__info * profile_info +#define STBIR_ONLY_PROFILE_BUILD_SET_INFO ,profile_info + +// super light-weight micro profiler +#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded; +#define STBIR_PROFILE_END_ll( info, wh ) wh##thiszonetime = STBIR_PROFILE_FUNC() - wh##thiszonetime; info->profile.named.wh += wh##thiszonetime - wh##current_zone_excluded; *wh##save_parent_excluded_ptr += wh##thiszonetime; info->current_zone_excluded_ptr = wh##save_parent_excluded_ptr; } +#define STBIR_PROFILE_FIRST_START_ll( info, wh ) { int i; info->current_zone_excluded_ptr = &info->profile.named.total; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } STBIR_PROFILE_START_ll( info, wh ); +#define STBIR_PROFILE_CLEAR_EXTRAS_ll( info, num ) { int extra; for(extra=1;extra<(num);extra++) { int i; for(i=0;iprofile.array);i++) (info)[extra].profile.array[i]=0; } } + +// for thread data +#define STBIR_PROFILE_START( wh ) STBIR_PROFILE_START_ll( split_info, wh ) +#define STBIR_PROFILE_END( wh ) STBIR_PROFILE_END_ll( split_info, wh ) +#define STBIR_PROFILE_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( split_info, wh ) +#define STBIR_PROFILE_CLEAR_EXTRAS() STBIR_PROFILE_CLEAR_EXTRAS_ll( split_info, split_count ) + +// for build data +#define STBIR_PROFILE_BUILD_START( wh ) STBIR_PROFILE_START_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_END( wh ) STBIR_PROFILE_END_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_CLEAR( info ) { int i; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } + +#else // no profile + +#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO +#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO + +#define STBIR_ONLY_PROFILE_BUILD_GET_INFO +#define STBIR_ONLY_PROFILE_BUILD_SET_INFO + +#define STBIR_PROFILE_START( wh ) +#define STBIR_PROFILE_END( wh ) +#define STBIR_PROFILE_FIRST_START( wh ) +#define STBIR_PROFILE_CLEAR_EXTRAS( ) + +#define STBIR_PROFILE_BUILD_START( wh ) +#define STBIR_PROFILE_BUILD_END( wh ) +#define STBIR_PROFILE_BUILD_FIRST_START( wh ) +#define STBIR_PROFILE_BUILD_CLEAR( info ) + +#endif // stbir_profile + +#ifndef STBIR_CEILF +#include +#if _MSC_VER <= 1200 // support VC6 for Sean +#define STBIR_CEILF(x) ((float)ceil((float)(x))) +#define STBIR_FLOORF(x) ((float)floor((float)(x))) +#else +#define STBIR_CEILF(x) ceilf(x) +#define STBIR_FLOORF(x) floorf(x) +#endif +#endif + +#ifndef STBIR_MEMCPY +// For memcpy +#include +#define STBIR_MEMCPY( dest, src, len ) memcpy( dest, src, len ) +#endif + +#ifndef STBIR_SIMD + +// memcpy that is specifically intentionally overlapping (src is smaller then dest, so can be +// a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to +// the diff between dest and src) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; + ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; + + if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away? + { + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7); + STBIR_NO_UNROLL_LOOP_START + do + { + STBIR_NO_UNROLL(sd); + *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; + sd += 8; + } while ( sd < s_end8 ); + + if ( sd == s_end ) + return; + } + + STBIR_NO_UNROLL_LOOP_START + do + { + STBIR_NO_UNROLL(sd); + *(int*)( sd + ofs_to_dest ) = *(int*) sd; + sd += 4; + } while ( sd < s_end ); +} + +#endif + +static float stbir__filter_trapezoid(float x, float scale, void * user_data) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x >= t) + return 0.0f; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1.0f; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale, void * user_data) +{ + STBIR__UNUSED(user_data); + return 0.5f + scale / 2.0f; +} + +static float stbir__filter_triangle(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x <= 1.0f) + return 1.0f - x; + else + return 0.0f; +} + +static float stbir__filter_point(float x, float s, void * user_data) +{ + STBIR__UNUSED(x); + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + return 1.0f; +} + +static float stbir__filter_cubic(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return (4.0f + x*x*(3.0f*x - 6.0f))/6.0f; + else if (x < 2.0f) + return (8.0f + x*(-12.0f + x*(6.0f - x)))/6.0f; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return 1.0f - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2.0f - x*(4.0f + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return (16.0f + x*x*(21.0f * x - 36.0f))/18.0f; + else if (x < 2.0f) + return (32.0f + x*(-60.0f + x*(36.0f - 7.0f*x)))/18.0f; + + return (0.0f); +} + +static float stbir__support_zeropoint5(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 0.5f; +} + +static float stbir__support_one(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 1; +} + +static float stbir__support_two(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 2; +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter from the output pixel's perspective +static int stbir__get_filter_pixel_width(stbir__support_callback * support, float scale, void * user_data) +{ + STBIR_ASSERT(support != 0); + + if ( scale >= ( 1.0f-stbir__small_float ) ) // upscale + return (int)STBIR_CEILF(support(1.0f/scale,user_data) * 2.0f); + else + return (int)STBIR_CEILF(support(scale,user_data) * 2.0f / scale); +} + +// this is how many coefficents per run of the filter (which is different +// from the filter_pixel_width depending on if we are scattering or gathering) +static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, void * user_data) +{ + float scale = samp->scale_info.scale; + stbir__support_callback * support = samp->filter_support; + + switch( is_gather ) + { + case 1: + return (int)STBIR_CEILF(support(1.0f / scale, user_data) * 2.0f); + case 2: + return (int)STBIR_CEILF(support(scale, user_data) * 2.0f / scale); + case 0: + return (int)STBIR_CEILF(support(scale, user_data) * 2.0f); + default: + STBIR_ASSERT( (is_gather >= 0 ) && (is_gather <= 2 ) ); + return 0; + } +} + +static int stbir__get_contributors(stbir__sampler * samp, int is_gather) +{ + if (is_gather) + return samp->scale_info.output_sub_size; + else + return (samp->scale_info.input_full_size + samp->filter_pixel_margin * 2); +} + +static int stbir__edge_zero_full( int n, int max ) +{ + STBIR__UNUSED(n); + STBIR__UNUSED(max); + return 0; // NOTREACHED +} + +static int stbir__edge_clamp_full( int n, int max ) +{ + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED +} + +static int stbir__edge_reflect_full( int n, int max ) +{ + if (n < 0) + { + if (n > -max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED +} + +static int stbir__edge_wrap_full( int n, int max ) +{ + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } +} + +typedef int stbir__edge_wrap_func( int n, int max ); +static stbir__edge_wrap_func * stbir__edge_wrap_slow[] = +{ + stbir__edge_clamp_full, // STBIR_EDGE_CLAMP + stbir__edge_reflect_full, // STBIR_EDGE_REFLECT + stbir__edge_wrap_full, // STBIR_EDGE_WRAP + stbir__edge_zero_full, // STBIR_EDGE_ZERO +}; + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow[edge]( n, max ); +} + +#define STBIR__MERGE_RUNS_PIXEL_THRESHOLD 16 + +// get information on the extents of a sampler +static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline_extents ) +{ + int j, stop; + int left_margin, right_margin; + int min_n = 0x7fffffff, max_n = -0x7fffffff; + int min_left = 0x7fffffff, max_left = -0x7fffffff; + int min_right = 0x7fffffff, max_right = -0x7fffffff; + stbir_edge edge = samp->edge; + stbir__contributors* contributors = samp->contributors; + int output_sub_size = samp->scale_info.output_sub_size; + int input_full_size = samp->scale_info.input_full_size; + int filter_pixel_margin = samp->filter_pixel_margin; + + STBIR_ASSERT( samp->is_gather ); + + stop = output_sub_size; + for (j = 0; j < stop; j++ ) + { + STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 ); + if ( contributors[j].n0 < min_n ) + { + min_n = contributors[j].n0; + stop = j + filter_pixel_margin; // if we find a new min, only scan another filter width + if ( stop > output_sub_size ) stop = output_sub_size; + } + } + + stop = 0; + for (j = output_sub_size - 1; j >= stop; j-- ) + { + STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 ); + if ( contributors[j].n1 > max_n ) + { + max_n = contributors[j].n1; + stop = j - filter_pixel_margin; // if we find a new max, only scan another filter width + if (stop<0) stop = 0; + } + } + + STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n ); + STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n ); + + // now calculate how much into the margins we really read + left_margin = 0; + if ( min_n < 0 ) + { + left_margin = -min_n; + min_n = 0; + } + + right_margin = 0; + if ( max_n >= input_full_size ) + { + right_margin = max_n - input_full_size + 1; + max_n = input_full_size - 1; + } + + // index 1 is margin pixel extents (how many pixels we hang over the edge) + scanline_extents->edge_sizes[0] = left_margin; + scanline_extents->edge_sizes[1] = right_margin; + + // index 2 is pixels read from the input + scanline_extents->spans[0].n0 = min_n; + scanline_extents->spans[0].n1 = max_n; + scanline_extents->spans[0].pixel_offset_for_input = min_n; + + // default to no other input range + scanline_extents->spans[1].n0 = 0; + scanline_extents->spans[1].n1 = -1; + scanline_extents->spans[1].pixel_offset_for_input = 0; + + // don't have to do edge calc for zero clamp + if ( edge == STBIR_EDGE_ZERO ) + return; + + // convert margin pixels to the pixels within the input (min and max) + for( j = -left_margin ; j < 0 ; j++ ) + { + int p = stbir__edge_wrap( edge, j, input_full_size ); + if ( p < min_left ) + min_left = p; + if ( p > max_left ) + max_left = p; + } + + for( j = input_full_size ; j < (input_full_size + right_margin) ; j++ ) + { + int p = stbir__edge_wrap( edge, j, input_full_size ); + if ( p < min_right ) + min_right = p; + if ( p > max_right ) + max_right = p; + } + + // merge the left margin pixel region if it connects within 4 pixels of main pixel region + if ( min_left != 0x7fffffff ) + { + if ( ( ( min_left <= min_n ) && ( ( max_left + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) || + ( ( min_n <= min_left ) && ( ( max_n + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_left ) ) ) + { + scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_left ); + scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_left ); + scanline_extents->spans[0].pixel_offset_for_input = min_n; + left_margin = 0; + } + } + + // merge the right margin pixel region if it connects within 4 pixels of main pixel region + if ( min_right != 0x7fffffff ) + { + if ( ( ( min_right <= min_n ) && ( ( max_right + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) || + ( ( min_n <= min_right ) && ( ( max_n + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_right ) ) ) + { + scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_right ); + scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_right ); + scanline_extents->spans[0].pixel_offset_for_input = min_n; + right_margin = 0; + } + } + + STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n ); + STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n ); + + // you get two ranges when you have the WRAP edge mode and you are doing just the a piece of the resize + // so you need to get a second run of pixels from the opposite side of the scanline (which you + // wouldn't need except for WRAP) + + + // if we can't merge the min_left range, add it as a second range + if ( ( left_margin ) && ( min_left != 0x7fffffff ) ) + { + stbir__span * newspan = scanline_extents->spans + 1; + STBIR_ASSERT( right_margin == 0 ); + if ( min_left < scanline_extents->spans[0].n0 ) + { + scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1; + --newspan; + } + newspan->pixel_offset_for_input = min_left; + newspan->n0 = -left_margin; + newspan->n1 = ( max_left - min_left ) - left_margin; + scanline_extents->edge_sizes[0] = 0; // don't need to copy the left margin, since we are directly decoding into the margin + return; + } + + // if we can't merge the min_left range, add it as a second range + if ( ( right_margin ) && ( min_right != 0x7fffffff ) ) + { + stbir__span * newspan = scanline_extents->spans + 1; + if ( min_right < scanline_extents->spans[0].n0 ) + { + scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1; + --newspan; + } + newspan->pixel_offset_for_input = min_right; + newspan->n0 = scanline_extents->spans[1].n1 + 1; + newspan->n1 = scanline_extents->spans[1].n1 + 1 + ( max_right - min_right ); + scanline_extents->edge_sizes[1] = 0; // don't need to copy the right margin, since we are directly decoding into the margin + return; + } +} + +static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel, float out_pixel_center, float out_filter_radius, float inv_scale, float out_shift, int input_size, stbir_edge edge ) +{ + int first, last; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale; + + first = (int)(STBIR_FLOORF(in_pixel_influence_lowerbound + 0.5f)); + last = (int)(STBIR_FLOORF(in_pixel_influence_upperbound - 0.5f)); + if ( last < first ) last = first; // point sample mode can span a value *right* at 0.5, and cause these to cross + + if ( edge == STBIR_EDGE_WRAP ) + { + if ( first < -input_size ) + first = -input_size; + if ( last >= (input_size*2)) + last = (input_size*2) - 1; + } + + *first_pixel = first; + *last_pixel = last; +} + +static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float* coefficient_group, int coefficient_width, stbir_edge edge, void * user_data ) +{ + int n, end; + float inv_scale = scale_info->inv_scale; + float out_shift = scale_info->pixel_shift; + int input_size = scale_info->input_full_size; + int numerator = scale_info->scale_numerator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) ); + + // Looping through out pixels + end = num_contributors; if ( polyphase ) end = numerator; + for (n = 0; n < end; n++) + { + int i; + int last_non_zero; + float out_pixel_center = (float)n + 0.5f; + float in_center_of_out = (out_pixel_center + out_shift) * inv_scale; + + int in_first_pixel, in_last_pixel; + + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, out_pixel_center, out_filter_radius, inv_scale, out_shift, input_size, edge ); + + // make sure we never generate a range larger than our precalculated coeff width + // this only happens in point sample mode, but it's a good safe thing to do anyway + if ( ( in_last_pixel - in_first_pixel + 1 ) > coefficient_width ) + in_last_pixel = in_first_pixel + coefficient_width - 1; + + last_non_zero = -1; + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + float coeff = kernel(in_center_of_out - in_pixel_center, inv_scale, user_data); + + // kill denormals + if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) + { + if ( i == 0 ) // if we're at the front, just eat zero contributors + { + STBIR_ASSERT ( ( in_last_pixel - in_first_pixel ) != 0 ); // there should be at least one contrib + ++in_first_pixel; + i--; + continue; + } + coeff = 0; // make sure is fully zero (should keep denormals away) + } + else + last_non_zero = i; + + coefficient_group[i] = coeff; + } + + in_last_pixel = last_non_zero+in_first_pixel; // kills trailing zeros + contributors->n0 = in_first_pixel; + contributors->n1 = in_last_pixel; + + STBIR_ASSERT(contributors->n1 >= contributors->n0); + + ++contributors; + coefficient_group += coefficient_width; + } +} + +static void stbir__insert_coeff( stbir__contributors * contribs, float * coeffs, int new_pixel, float new_coeff, int max_width ) +{ + if ( new_pixel <= contribs->n1 ) // before the end + { + if ( new_pixel < contribs->n0 ) // before the front? + { + if ( ( contribs->n1 - new_pixel + 1 ) <= max_width ) + { + int j, o = contribs->n0 - new_pixel; + for ( j = contribs->n1 - contribs->n0 ; j <= 0 ; j-- ) + coeffs[ j + o ] = coeffs[ j ]; + for ( j = 1 ; j < o ; j-- ) + coeffs[ j ] = coeffs[ 0 ]; + coeffs[ 0 ] = new_coeff; + contribs->n0 = new_pixel; + } + } + else + { + coeffs[ new_pixel - contribs->n0 ] += new_coeff; + } + } + else + { + if ( ( new_pixel - contribs->n0 + 1 ) <= max_width ) + { + int j, e = new_pixel - contribs->n0; + for( j = ( contribs->n1 - contribs->n0 ) + 1 ; j < e ; j++ ) // clear in-betweens coeffs if there are any + coeffs[j] = 0; + + coeffs[ e ] = new_coeff; + contribs->n1 = new_pixel; + } + } +} + +static void stbir__calculate_out_pixel_range( int * first_pixel, int * last_pixel, float in_pixel_center, float in_pixels_radius, float scale, float out_shift, int out_size ) +{ + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale - out_shift; + int out_first_pixel = (int)(STBIR_FLOORF(out_pixel_influence_lowerbound + 0.5f)); + int out_last_pixel = (int)(STBIR_FLOORF(out_pixel_influence_upperbound - 0.5f)); + + if ( out_first_pixel < 0 ) + out_first_pixel = 0; + if ( out_last_pixel >= out_size ) + out_last_pixel = out_size - 1; + *first_pixel = out_first_pixel; + *last_pixel = out_last_pixel; +} + +static void stbir__calculate_coefficients_for_gather_downsample( int start, int end, float in_pixels_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int coefficient_width, int num_contributors, stbir__contributors * contributors, float * coefficient_group, void * user_data ) +{ + int in_pixel; + int i; + int first_out_inited = -1; + float scale = scale_info->scale; + float out_shift = scale_info->pixel_shift; + int out_size = scale_info->output_sub_size; + int numerator = scale_info->scale_numerator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < out_size ) ); + + STBIR__UNUSED(num_contributors); + + // Loop through the input pixels + for (in_pixel = start; in_pixel < end; in_pixel++) + { + float in_pixel_center = (float)in_pixel + 0.5f; + float out_center_of_in = in_pixel_center * scale - out_shift; + int out_first_pixel, out_last_pixel; + + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, in_pixel_center, in_pixels_radius, scale, out_shift, out_size ); + + if ( out_first_pixel > out_last_pixel ) + continue; + + // clamp or exit if we are using polyphase filtering, and the limit is up + if ( polyphase ) + { + // when polyphase, you only have to do coeffs up to the numerator count + if ( out_first_pixel == numerator ) + break; + + // don't do any extra work, clamp last pixel at numerator too + if ( out_last_pixel >= numerator ) + out_last_pixel = numerator - 1; + } + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + float coeff = kernel(x, scale, user_data) * scale; + + // kill the coeff if it's too small (avoid denormals) + if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) + coeff = 0.0f; + + { + int out = i + out_first_pixel; + float * coeffs = coefficient_group + out * coefficient_width; + stbir__contributors * contribs = contributors + out; + + // is this the first time this output pixel has been seen? Init it. + if ( out > first_out_inited ) + { + STBIR_ASSERT( out == ( first_out_inited + 1 ) ); // ensure we have only advanced one at time + first_out_inited = out; + contribs->n0 = in_pixel; + contribs->n1 = in_pixel; + coeffs[0] = coeff; + } + else + { + // insert on end (always in order) + if ( coeffs[0] == 0.0f ) // if the first coefficent is zero, then zap it for this coeffs + { + STBIR_ASSERT( ( in_pixel - contribs->n0 ) == 1 ); // ensure that when we zap, we're at the 2nd pos + contribs->n0 = in_pixel; + } + contribs->n1 = in_pixel; + STBIR_ASSERT( ( in_pixel - contribs->n0 ) < coefficient_width ); + coeffs[in_pixel - contribs->n0] = coeff; + } + } + } + } +} + +#ifdef STBIR_RENORMALIZE_IN_FLOAT +#define STBIR_RENORM_TYPE float +#else +#define STBIR_RENORM_TYPE double +#endif + +static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width ) +{ + int input_size = scale_info->input_full_size; + int input_last_n1 = input_size - 1; + int n, end; + int lowest = 0x7fffffff; + int highest = -0x7fffffff; + int widest = -1; + int numerator = scale_info->scale_numerator; + int denominator = scale_info->scale_denominator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) ); + float * coeffs; + stbir__contributors * contribs; + + // weight all the coeffs for each sample + coeffs = coefficient_group; + contribs = contributors; + end = num_contributors; if ( polyphase ) end = numerator; + for (n = 0; n < end; n++) + { + int i; + STBIR_RENORM_TYPE filter_scale, total_filter = 0; + int e; + + // add all contribs + e = contribs->n1 - contribs->n0; + for( i = 0 ; i <= e ; i++ ) + { + total_filter += (STBIR_RENORM_TYPE) coeffs[i]; + STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f ) ); // check for wonky weights + } + + // rescale + if ( ( total_filter < stbir__small_float ) && ( total_filter > -stbir__small_float ) ) + { + // all coeffs are extremely small, just zero it + contribs->n1 = contribs->n0; + coeffs[0] = 0.0f; + } + else + { + // if the total isn't 1.0, rescale everything + if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) ) + { + filter_scale = ((STBIR_RENORM_TYPE)1.0) / total_filter; + + // scale them all + for (i = 0; i <= e; i++) + coeffs[i] = (float) ( coeffs[i] * filter_scale ); + } + } + ++contribs; + coeffs += coefficient_width; + } + + // if we have a rational for the scale, we can exploit the polyphaseness to not calculate + // most of the coefficients, so we copy them here + if ( polyphase ) + { + stbir__contributors * prev_contribs = contributors; + stbir__contributors * cur_contribs = contributors + numerator; + + for( n = numerator ; n < num_contributors ; n++ ) + { + cur_contribs->n0 = prev_contribs->n0 + denominator; + cur_contribs->n1 = prev_contribs->n1 + denominator; + ++cur_contribs; + ++prev_contribs; + } + stbir_overlapping_memcpy( coefficient_group + numerator * coefficient_width, coefficient_group, ( num_contributors - numerator ) * coefficient_width * sizeof( coeffs[ 0 ] ) ); + } + + coeffs = coefficient_group; + contribs = contributors; + + for (n = 0; n < num_contributors; n++) + { + int i; + + // in zero edge mode, just remove out of bounds contribs completely (since their weights are accounted for now) + if ( edge == STBIR_EDGE_ZERO ) + { + // shrink the right side if necessary + if ( contribs->n1 > input_last_n1 ) + contribs->n1 = input_last_n1; + + // shrink the left side + if ( contribs->n0 < 0 ) + { + int j, left, skips = 0; + + skips = -contribs->n0; + contribs->n0 = 0; + + // now move down the weights + left = contribs->n1 - contribs->n0 + 1; + if ( left > 0 ) + { + for( j = 0 ; j < left ; j++ ) + coeffs[ j ] = coeffs[ j + skips ]; + } + } + } + else if ( ( edge == STBIR_EDGE_CLAMP ) || ( edge == STBIR_EDGE_REFLECT ) ) + { + // for clamp and reflect, calculate the true inbounds position (based on edge type) and just add that to the existing weight + + // right hand side first + if ( contribs->n1 > input_last_n1 ) + { + int start = contribs->n0; + int endi = contribs->n1; + contribs->n1 = input_last_n1; + for( i = input_size; i <= endi; i++ ) + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), coeffs[i-start], coefficient_width ); + } + + // now check left hand edge + if ( contribs->n0 < 0 ) + { + int save_n0; + float save_n0_coeff; + float * c = coeffs - ( contribs->n0 + 1 ); + + // reinsert the coeffs with it reflected or clamped (insert accumulates, if the coeffs exist) + for( i = -1 ; i > contribs->n0 ; i-- ) + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), *c--, coefficient_width ); + save_n0 = contribs->n0; + save_n0_coeff = c[0]; // save it, since we didn't do the final one (i==n0), because there might be too many coeffs to hold (before we resize)! + + // now slide all the coeffs down (since we have accumulated them in the positive contribs) and reset the first contrib + contribs->n0 = 0; + for(i = 0 ; i <= contribs->n1 ; i++ ) + coeffs[i] = coeffs[i-save_n0]; + + // now that we have shrunk down the contribs, we insert the first one safely + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( save_n0, input_size ), save_n0_coeff, coefficient_width ); + } + } + + if ( contribs->n0 <= contribs->n1 ) + { + int diff = contribs->n1 - contribs->n0 + 1; + while ( diff && ( coeffs[ diff-1 ] == 0.0f ) ) + --diff; + + contribs->n1 = contribs->n0 + diff - 1; + + if ( contribs->n0 <= contribs->n1 ) + { + if ( contribs->n0 < lowest ) + lowest = contribs->n0; + if ( contribs->n1 > highest ) + highest = contribs->n1; + if ( diff > widest ) + widest = diff; + } + + // re-zero out unused coefficients (if any) + for( i = diff ; i < coefficient_width ; i++ ) + coeffs[i] = 0.0f; + } + + ++contribs; + coeffs += coefficient_width; + } + filter_info->lowest = lowest; + filter_info->highest = highest; + filter_info->widest = widest; +} + +#undef STBIR_RENORM_TYPE + +static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row0, int row1 ) +{ + #define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; } + #define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; } + #ifdef STBIR_SIMD + #define STBIR_MOVE_4( dest, src ) { stbir__simdf t; STBIR_NO_UNROLL(dest); stbir__simdf_load( t, src ); stbir__simdf_store( dest, t ); } + #else + #define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; } + #endif + + int row_end = row1 + 1; + STBIR__UNUSED( row0 ); // only used in an assert + + if ( coefficient_width != widest ) + { + float * pc = coefficents; + float * coeffs = coefficents; + float * pc_end = coefficents + num_contributors * widest; + switch( widest ) + { + case 1: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_1( pc, coeffs ); + ++pc; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 2: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_2( pc, coeffs ); + pc += 2; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 3: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_2( pc, coeffs ); + STBIR_MOVE_1( pc+2, coeffs+2 ); + pc += 3; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 4: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + pc += 4; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 5: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_1( pc+4, coeffs+4 ); + pc += 5; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 6: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_2( pc+4, coeffs+4 ); + pc += 6; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 7: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_2( pc+4, coeffs+4 ); + STBIR_MOVE_1( pc+6, coeffs+6 ); + pc += 7; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 8: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + pc += 8; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 9: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_1( pc+8, coeffs+8 ); + pc += 9; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 10: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_2( pc+8, coeffs+8 ); + pc += 10; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 11: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_2( pc+8, coeffs+8 ); + STBIR_MOVE_1( pc+10, coeffs+10 ); + pc += 11; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 12: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_4( pc+8, coeffs+8 ); + pc += 12; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + default: + STBIR_NO_UNROLL_LOOP_START + do { + float * copy_end = pc + widest - 4; + float * c = coeffs; + do { + STBIR_NO_UNROLL( pc ); + STBIR_MOVE_4( pc, c ); + pc += 4; + c += 4; + } while ( pc <= copy_end ); + copy_end += 4; + STBIR_NO_UNROLL_LOOP_START + while ( pc < copy_end ) + { + STBIR_MOVE_1( pc, c ); + ++pc; ++c; + } + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + } + } + + // some horizontal routines read one float off the end (which is then masked off), so put in a sentinal so we don't read an snan or denormal + coefficents[ widest * num_contributors ] = 8888.0f; + + // the minimum we might read for unrolled filters widths is 12. So, we need to + // make sure we never read outside the decode buffer, by possibly moving + // the sample area back into the scanline, and putting zeros weights first. + // we start on the right edge and check until we're well past the possible + // clip area (2*widest). + { + stbir__contributors * contribs = contributors + num_contributors - 1; + float * coeffs = coefficents + widest * ( num_contributors - 1 ); + + // go until no chance of clipping (this is usually less than 8 lops) + while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_end ) ) + { + // might we clip?? + if ( ( contribs->n0 + widest ) > row_end ) + { + int stop_range = widest; + + // if range is larger than 12, it will be handled by generic loops that can terminate on the exact length + // of this contrib n1, instead of a fixed widest amount - so calculate this + if ( widest > 12 ) + { + int mod; + + // how far will be read in the n_coeff loop (which depends on the widest count mod4); + mod = widest & 3; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + + // the n_coeff loops do a minimum amount of coeffs, so factor that in! + if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; + } + + // now see if we still clip with the refined range + if ( ( contribs->n0 + stop_range ) > row_end ) + { + int new_n0 = row_end - stop_range; + int num = contribs->n1 - contribs->n0 + 1; + int backup = contribs->n0 - new_n0; + float * from_co = coeffs + num - 1; + float * to_co = from_co + backup; + + STBIR_ASSERT( ( new_n0 >= row0 ) && ( new_n0 < contribs->n0 ) ); + + // move the coeffs over + while( num ) + { + *to_co-- = *from_co--; + --num; + } + // zero new positions + while ( to_co >= coeffs ) + *to_co-- = 0; + // set new start point + contribs->n0 = new_n0; + if ( widest > 12 ) + { + int mod; + + // how far will be read in the n_coeff loop (which depends on the widest count mod4); + mod = widest & 3; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + + // the n_coeff loops do a minimum amount of coeffs, so factor that in! + if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; + } + } + } + --contribs; + coeffs -= widest; + } + } + + return widest; + #undef STBIR_MOVE_1 + #undef STBIR_MOVE_2 + #undef STBIR_MOVE_4 +} + +static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * other_axis_for_pivot, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO ) +{ + int n; + float scale = samp->scale_info.scale; + stbir__kernel_callback * kernel = samp->filter_kernel; + stbir__support_callback * support = samp->filter_support; + float inv_scale = samp->scale_info.inv_scale; + int input_full_size = samp->scale_info.input_full_size; + int gather_num_contributors = samp->num_contributors; + stbir__contributors* gather_contributors = samp->contributors; + float * gather_coeffs = samp->coefficients; + int gather_coefficient_width = samp->coefficient_width; + + switch ( samp->is_gather ) + { + case 1: // gather upsample + { + float out_pixels_radius = support(inv_scale,user_data) * scale; + + stbir__calculate_coefficients_for_gather_upsample( out_pixels_radius, kernel, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width, samp->edge, user_data ); + + STBIR_PROFILE_BUILD_START( cleanup ); + stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width ); + STBIR_PROFILE_BUILD_END( cleanup ); + } + break; + + case 0: // scatter downsample (only on vertical) + case 2: // gather downsample + { + float in_pixels_radius = support(scale,user_data) * inv_scale; + int filter_pixel_margin = samp->filter_pixel_margin; + int input_end = input_full_size + filter_pixel_margin; + + // if this is a scatter, we do a downsample gather to get the coeffs, and then pivot after + if ( !samp->is_gather ) + { + // check if we are using the same gather downsample on the horizontal as this vertical, + // if so, then we don't have to generate them, we can just pivot from the horizontal. + if ( other_axis_for_pivot ) + { + gather_contributors = other_axis_for_pivot->contributors; + gather_coeffs = other_axis_for_pivot->coefficients; + gather_coefficient_width = other_axis_for_pivot->coefficient_width; + gather_num_contributors = other_axis_for_pivot->num_contributors; + samp->extent_info.lowest = other_axis_for_pivot->extent_info.lowest; + samp->extent_info.highest = other_axis_for_pivot->extent_info.highest; + samp->extent_info.widest = other_axis_for_pivot->extent_info.widest; + goto jump_right_to_pivot; + } + + gather_contributors = samp->gather_prescatter_contributors; + gather_coeffs = samp->gather_prescatter_coefficients; + gather_coefficient_width = samp->gather_prescatter_coefficient_width; + gather_num_contributors = samp->gather_prescatter_num_contributors; + } + + stbir__calculate_coefficients_for_gather_downsample( -filter_pixel_margin, input_end, in_pixels_radius, kernel, &samp->scale_info, gather_coefficient_width, gather_num_contributors, gather_contributors, gather_coeffs, user_data ); + + STBIR_PROFILE_BUILD_START( cleanup ); + stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width ); + STBIR_PROFILE_BUILD_END( cleanup ); + + if ( !samp->is_gather ) + { + // if this is a scatter (vertical only), then we need to pivot the coeffs + stbir__contributors * scatter_contributors; + int highest_set; + + jump_right_to_pivot: + + STBIR_PROFILE_BUILD_START( pivot ); + + highest_set = (-filter_pixel_margin) - 1; + for (n = 0; n < gather_num_contributors; n++) + { + int k; + int gn0 = gather_contributors->n0, gn1 = gather_contributors->n1; + int scatter_coefficient_width = samp->coefficient_width; + float * scatter_coeffs = samp->coefficients + ( gn0 + filter_pixel_margin ) * scatter_coefficient_width; + float * g_coeffs = gather_coeffs; + scatter_contributors = samp->contributors + ( gn0 + filter_pixel_margin ); + + for (k = gn0 ; k <= gn1 ; k++ ) + { + float gc = *g_coeffs++; + + // skip zero and denormals - must skip zeros to avoid adding coeffs beyond scatter_coefficient_width + // (which happens when pivoting from horizontal, which might have dummy zeros) + if ( ( ( gc >= stbir__small_float ) || ( gc <= -stbir__small_float ) ) ) + { + if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) ) + { + { + // if we are skipping over several contributors, we need to clear the skipped ones + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + while ( clear_contributors < scatter_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } + } + scatter_contributors->n0 = n; + scatter_contributors->n1 = n; + scatter_coeffs[0] = gc; + highest_set = k; + } + else + { + stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc, scatter_coefficient_width ); + } + STBIR_ASSERT( ( scatter_contributors->n1 - scatter_contributors->n0 + 1 ) <= scatter_coefficient_width ); + } + ++scatter_contributors; + scatter_coeffs += scatter_coefficient_width; + } + + ++gather_contributors; + gather_coeffs += gather_coefficient_width; + } + + // now clear any unset contribs + { + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + stbir__contributors * end_contributors = samp->contributors + samp->num_contributors; + while ( clear_contributors < end_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } + } + + STBIR_PROFILE_BUILD_END( pivot ); + } + } + break; + } +} + + +//======================================================================================================== +// scanline decoders and encoders + +#define stbir__coder_min_num 1 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix BGRA +#define stbir__decode_swizzle +#define stbir__decode_order0 2 +#define stbir__decode_order1 1 +#define stbir__decode_order2 0 +#define stbir__decode_order3 3 +#define stbir__encode_order0 2 +#define stbir__encode_order1 1 +#define stbir__encode_order2 0 +#define stbir__encode_order3 3 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix ARGB +#define stbir__decode_swizzle +#define stbir__decode_order0 1 +#define stbir__decode_order1 2 +#define stbir__decode_order2 3 +#define stbir__decode_order3 0 +#define stbir__encode_order0 3 +#define stbir__encode_order1 0 +#define stbir__encode_order2 1 +#define stbir__encode_order3 2 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix ABGR +#define stbir__decode_swizzle +#define stbir__decode_order0 3 +#define stbir__decode_order1 2 +#define stbir__decode_order2 1 +#define stbir__decode_order3 0 +#define stbir__encode_order0 3 +#define stbir__encode_order1 2 +#define stbir__encode_order2 1 +#define stbir__encode_order3 0 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix AR +#define stbir__decode_swizzle +#define stbir__decode_order0 1 +#define stbir__decode_order1 0 +#define stbir__decode_order2 3 +#define stbir__decode_order3 2 +#define stbir__encode_order0 1 +#define stbir__encode_order1 0 +#define stbir__encode_order2 3 +#define stbir__encode_order3 2 +#define stbir__coder_min_num 2 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + + +// fancy alpha means we expand to keep both premultipied and non-premultiplied color channels +static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) out = out_buffer; + float const * end_decode = out_buffer + ( width_times_channels / 4 ) * 7; // decode buffer aligned to end of out_buffer + float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels; + + // fancy alpha is stored internally as R G B A Rpm Gpm Bpm + + #ifdef STBIR_SIMD + + #ifdef STBIR_SIMD8 + decode += 16; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdf8 d0,d1,a0,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf8_load( d0, decode-16 ); + stbir__simdf8_load( d1, decode-16+8 ); + stbir__simdf8_0123to33333333( a0, d0 ); + stbir__simdf8_0123to33333333( a1, d1 ); + stbir__simdf8_mult( p0, a0, d0 ); + stbir__simdf8_mult( p1, a1, d1 ); + stbir__simdf8_bot4s( a0, d0, p0 ); + stbir__simdf8_bot4s( a1, d1, p1 ); + stbir__simdf8_top4s( d0, d0, p0 ); + stbir__simdf8_top4s( d1, d1, p1 ); + stbir__simdf8_store ( out, a0 ); + stbir__simdf8_store ( out+7, d0 ); + stbir__simdf8_store ( out+14, a1 ); + stbir__simdf8_store ( out+21, d1 ); + decode += 16; + out += 28; + } + decode -= 16; + #else + decode += 8; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdf d0,a0,d1,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d0, decode-8 ); + stbir__simdf_load( d1, decode-8+4 ); + stbir__simdf_0123to3333( a0, d0 ); + stbir__simdf_0123to3333( a1, d1 ); + stbir__simdf_mult( p0, a0, d0 ); + stbir__simdf_mult( p1, a1, d1 ); + stbir__simdf_store ( out, d0 ); + stbir__simdf_store ( out+4, p0 ); + stbir__simdf_store ( out+7, d1 ); + stbir__simdf_store ( out+7+4, p1 ); + decode += 8; + out += 14; + } + decode -= 8; + #endif + + // might be one last odd pixel + #ifdef STBIR_SIMD8 + STBIR_NO_UNROLL_LOOP_START + while ( decode < end_decode ) + #else + if ( decode < end_decode ) + #endif + { + stbir__simdf d,a,p; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d, decode ); + stbir__simdf_0123to3333( a, d ); + stbir__simdf_mult( p, a, d ); + stbir__simdf_store ( out, d ); + stbir__simdf_store ( out+4, p ); + decode += 4; + out += 7; + } + + #else + + while( decode < end_decode ) + { + float r = decode[0], g = decode[1], b = decode[2], alpha = decode[3]; + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = alpha; + out[4] = r * alpha; + out[5] = g * alpha; + out[6] = b * alpha; + out += 7; + decode += 4; + } + + #endif +} + +static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) out = out_buffer; + float const * end_decode = out_buffer + ( width_times_channels / 2 ) * 3; + float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels; + + // for fancy alpha, turns into: [X A Xpm][X A Xpm],etc + + #ifdef STBIR_SIMD + + decode += 8; + if ( decode <= end_decode ) + { + STBIR_NO_UNROLL_LOOP_START + do { + #ifdef STBIR_SIMD8 + stbir__simdf8 d0,a0,p0; + STBIR_NO_UNROLL(decode); + stbir__simdf8_load( d0, decode-8 ); + stbir__simdf8_0123to11331133( p0, d0 ); + stbir__simdf8_0123to00220022( a0, d0 ); + stbir__simdf8_mult( p0, p0, a0 ); + + stbir__simdf_store2( out, stbir__if_simdf8_cast_to_simdf4( d0 ) ); + stbir__simdf_store( out+2, stbir__if_simdf8_cast_to_simdf4( p0 ) ); + stbir__simdf_store2h( out+3, stbir__if_simdf8_cast_to_simdf4( d0 ) ); + + stbir__simdf_store2( out+6, stbir__simdf8_gettop4( d0 ) ); + stbir__simdf_store( out+8, stbir__simdf8_gettop4( p0 ) ); + stbir__simdf_store2h( out+9, stbir__simdf8_gettop4( d0 ) ); + #else + stbir__simdf d0,a0,d1,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d0, decode-8 ); + stbir__simdf_load( d1, decode-8+4 ); + stbir__simdf_0123to1133( p0, d0 ); + stbir__simdf_0123to1133( p1, d1 ); + stbir__simdf_0123to0022( a0, d0 ); + stbir__simdf_0123to0022( a1, d1 ); + stbir__simdf_mult( p0, p0, a0 ); + stbir__simdf_mult( p1, p1, a1 ); + + stbir__simdf_store2( out, d0 ); + stbir__simdf_store( out+2, p0 ); + stbir__simdf_store2h( out+3, d0 ); + + stbir__simdf_store2( out+6, d1 ); + stbir__simdf_store( out+8, p1 ); + stbir__simdf_store2h( out+9, d1 ); + #endif + decode += 8; + out += 12; + } while ( decode <= end_decode ); + } + decode -= 8; + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode < end_decode ) + { + float x = decode[0], y = decode[1]; + STBIR_SIMD_NO_UNROLL(decode); + out[0] = x; + out[1] = y; + out[2] = x * y; + out += 3; + decode += 2; + } +} + +static void stbir__fancy_alpha_unweight_4ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + // fancy RGBA is stored internally as R G B A Rpm Gpm Bpm + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float alpha = input[3]; +#ifdef STBIR_SIMD + stbir__simdf i,ia; + STBIR_SIMD_NO_UNROLL(encode); + if ( alpha < stbir__small_float ) + { + stbir__simdf_load( i, input ); + stbir__simdf_store( encode, i ); + } + else + { + stbir__simdf_load1frep4( ia, 1.0f / alpha ); + stbir__simdf_load( i, input+4 ); + stbir__simdf_mult( i, i, ia ); + stbir__simdf_store( encode, i ); + encode[3] = alpha; + } +#else + if ( alpha < stbir__small_float ) + { + encode[0] = input[0]; + encode[1] = input[1]; + encode[2] = input[2]; + } + else + { + float ialpha = 1.0f / alpha; + encode[0] = input[4] * ialpha; + encode[1] = input[5] * ialpha; + encode[2] = input[6] * ialpha; + } + encode[3] = alpha; +#endif + + input += 7; + encode += 4; + } while ( encode < end_output ); +} + +// format: [X A Xpm][X A Xpm] etc +static void stbir__fancy_alpha_unweight_2ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = input[1]; + encode[0] = input[0]; + if ( alpha >= stbir__small_float ) + encode[0] = input[2] / alpha; + encode[1] = alpha; + + input += 3; + encode += 2; + } while ( encode < end_output ); +} + +static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + #ifdef STBIR_SIMD + { + decode += 2 * stbir__simdfX_float_count; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdfX d0,a0,d1,a1; + STBIR_NO_UNROLL(decode); + stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count ); + stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count ); + stbir__simdfX_aaa1( a0, d0, STBIR_onesX ); + stbir__simdfX_aaa1( a1, d1, STBIR_onesX ); + stbir__simdfX_mult( d0, d0, a0 ); + stbir__simdfX_mult( d1, d1, a1 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 ); + decode += 2 * stbir__simdfX_float_count; + } + decode -= 2 * stbir__simdfX_float_count; + + // few last pixels remnants + #ifdef STBIR_SIMD8 + STBIR_NO_UNROLL_LOOP_START + while ( decode < end_decode ) + #else + if ( decode < end_decode ) + #endif + { + stbir__simdf d,a; + stbir__simdf_load( d, decode ); + stbir__simdf_aaa1( a, d, STBIR__CONSTF(STBIR_ones) ); + stbir__simdf_mult( d, d, a ); + stbir__simdf_store ( decode, d ); + decode += 4; + } + } + + #else + + while( decode < end_decode ) + { + float alpha = decode[3]; + decode[0] *= alpha; + decode[1] *= alpha; + decode[2] *= alpha; + decode += 4; + } + + #endif +} + +static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + #ifdef STBIR_SIMD + decode += 2 * stbir__simdfX_float_count; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdfX d0,a0,d1,a1; + STBIR_NO_UNROLL(decode); + stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count ); + stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count ); + stbir__simdfX_a1a1( a0, d0, STBIR_onesX ); + stbir__simdfX_a1a1( a1, d1, STBIR_onesX ); + stbir__simdfX_mult( d0, d0, a0 ); + stbir__simdfX_mult( d1, d1, a1 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 ); + decode += 2 * stbir__simdfX_float_count; + } + decode -= 2 * stbir__simdfX_float_count; + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode < end_decode ) + { + float alpha = decode[1]; + STBIR_SIMD_NO_UNROLL(decode); + decode[0] *= alpha; + decode += 2; + } +} + +static void stbir__simple_alpha_unweight_4ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float alpha = encode[3]; + +#ifdef STBIR_SIMD + stbir__simdf i,ia; + STBIR_SIMD_NO_UNROLL(encode); + if ( alpha >= stbir__small_float ) + { + stbir__simdf_load1frep4( ia, 1.0f / alpha ); + stbir__simdf_load( i, encode ); + stbir__simdf_mult( i, i, ia ); + stbir__simdf_store( encode, i ); + encode[3] = alpha; + } +#else + if ( alpha >= stbir__small_float ) + { + float ialpha = 1.0f / alpha; + encode[0] *= ialpha; + encode[1] *= ialpha; + encode[2] *= ialpha; + } +#endif + encode += 4; + } while ( encode < end_output ); +} + +static void stbir__simple_alpha_unweight_2ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = encode[1]; + if ( alpha >= stbir__small_float ) + encode[0] /= alpha; + encode += 2; + } while ( encode < end_output ); +} + + +// only used in RGB->BGR or BGR->RGB +static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + +#ifdef STBIR_SIMD + #ifdef stbir__simdf_swiz2 // do we have two argument swizzles? + end_decode -= 12; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // on arm64 8 instructions, no overlapping stores + stbir__simdf a,b,c,na,nb; + STBIR_SIMD_NO_UNROLL(decode); + stbir__simdf_load( a, decode ); + stbir__simdf_load( b, decode+4 ); + stbir__simdf_load( c, decode+8 ); + + na = stbir__simdf_swiz2( a, b, 2, 1, 0, 5 ); + b = stbir__simdf_swiz2( a, b, 4, 3, 6, 7 ); + nb = stbir__simdf_swiz2( b, c, 0, 1, 4, 3 ); + c = stbir__simdf_swiz2( b, c, 2, 7, 6, 5 ); + + stbir__simdf_store( decode, na ); + stbir__simdf_store( decode+4, nb ); + stbir__simdf_store( decode+8, c ); + decode += 12; + } + end_decode += 12; + #else + end_decode -= 24; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // 26 instructions on x64 + stbir__simdf a,b,c,d,e,f,g; + float i21, i23; + STBIR_SIMD_NO_UNROLL(decode); + stbir__simdf_load( a, decode ); + stbir__simdf_load( b, decode+3 ); + stbir__simdf_load( c, decode+6 ); + stbir__simdf_load( d, decode+9 ); + stbir__simdf_load( e, decode+12 ); + stbir__simdf_load( f, decode+15 ); + stbir__simdf_load( g, decode+18 ); + + a = stbir__simdf_swiz( a, 2, 1, 0, 3 ); + b = stbir__simdf_swiz( b, 2, 1, 0, 3 ); + c = stbir__simdf_swiz( c, 2, 1, 0, 3 ); + d = stbir__simdf_swiz( d, 2, 1, 0, 3 ); + e = stbir__simdf_swiz( e, 2, 1, 0, 3 ); + f = stbir__simdf_swiz( f, 2, 1, 0, 3 ); + g = stbir__simdf_swiz( g, 2, 1, 0, 3 ); + + // stores overlap, need to be in order, + stbir__simdf_store( decode, a ); + i21 = decode[21]; + stbir__simdf_store( decode+3, b ); + i23 = decode[23]; + stbir__simdf_store( decode+6, c ); + stbir__simdf_store( decode+9, d ); + stbir__simdf_store( decode+12, e ); + stbir__simdf_store( decode+15, f ); + stbir__simdf_store( decode+18, g ); + decode[21] = i23; + decode[23] = i21; + decode += 24; + } + end_decode += 24; + #endif +#else + end_decode -= 12; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // 16 instructions + float t0,t1,t2,t3; + STBIR_NO_UNROLL(decode); + t0 = decode[0]; t1 = decode[3]; t2 = decode[6]; t3 = decode[9]; + decode[0] = decode[2]; decode[3] = decode[5]; decode[6] = decode[8]; decode[9] = decode[11]; + decode[2] = t0; decode[5] = t1; decode[8] = t2; decode[11] = t3; + decode += 12; + } + end_decode += 12; +#endif + + STBIR_NO_UNROLL_LOOP_START + while( decode < end_decode ) + { + float t = decode[0]; + STBIR_NO_UNROLL(decode); + decode[0] = decode[2]; + decode[2] = t; + decode += 3; + } +} + + + +static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float * output_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + int channels = stbir_info->channels; + int effective_channels = stbir_info->effective_channels; + int input_sample_in_bytes = stbir__type_size[stbir_info->input_type] * channels; + stbir_edge edge_horizontal = stbir_info->horizontal.edge; + stbir_edge edge_vertical = stbir_info->vertical.edge; + int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size); + const void* input_plane_data = ( (char *) stbir_info->input_data ) + (size_t)row * (size_t) stbir_info->input_stride_bytes; + stbir__span const * spans = stbir_info->scanline_extents.spans; + float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels; + + // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed + STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) ); + + do + { + float * decode_buffer; + void const * input_data; + float * end_decode; + int width_times_channels; + int width; + + if ( spans->n1 < spans->n0 ) + break; + + width = spans->n1 + 1 - spans->n0; + decode_buffer = full_decode_buffer + spans->n0 * effective_channels; + end_decode = full_decode_buffer + ( spans->n1 + 1 ) * effective_channels; + width_times_channels = width * channels; + + // read directly out of input plane by default + input_data = ( (char*)input_plane_data ) + spans->pixel_offset_for_input * input_sample_in_bytes; + + // if we have an input callback, call it to get the input data + if ( stbir_info->in_pixels_cb ) + { + // call the callback with a temp buffer (that they can choose to use or not). the temp is just right aligned memory in the decode_buffer itself + input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data ); + } + + STBIR_PROFILE_START( decode ); + // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channelsdecode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data ); + STBIR_PROFILE_END( decode ); + + if (stbir_info->alpha_weight) + { + STBIR_PROFILE_START( alpha ); + stbir_info->alpha_weight( decode_buffer, width_times_channels ); + STBIR_PROFILE_END( alpha ); + } + + ++spans; + } while ( spans <= ( &stbir_info->scanline_extents.spans[1] ) ); + + // handle the edge_wrap filter (all other types are handled back out at the calculate_filter stage) + // basically the idea here is that if we have the whole scanline in memory, we don't redecode the + // wrapped edge pixels, and instead just memcpy them from the scanline into the edge positions + if ( ( edge_horizontal == STBIR_EDGE_WRAP ) && ( stbir_info->scanline_extents.edge_sizes[0] | stbir_info->scanline_extents.edge_sizes[1] ) ) + { + // this code only runs if we're in edge_wrap, and we're doing the entire scanline + int e, start_x[2]; + int input_full_size = stbir_info->horizontal.scale_info.input_full_size; + + start_x[0] = -stbir_info->scanline_extents.edge_sizes[0]; // left edge start x + start_x[1] = input_full_size; // right edge + + for( e = 0; e < 2 ; e++ ) + { + // do each margin + int margin = stbir_info->scanline_extents.edge_sizes[e]; + if ( margin ) + { + int x = start_x[e]; + float * marg = full_decode_buffer + x * effective_channels; + float const * src = full_decode_buffer + stbir__edge_wrap(edge_horizontal, x, input_full_size) * effective_channels; + STBIR_MEMCPY( marg, src, margin * effective_channels * sizeof(float) ); + } + } + } +} + + +//================= +// Do 1 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_mult1_mem( tot, c, decode ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2z( c, hc ); \ + stbir__simdf_load2( d, decode ); \ + stbir__simdf_mult( tot, c, d ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_add1( tot, tot, c ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_0123to2301( t, tot ); \ + stbir__simdf_add1( tot, tot, c ); \ + stbir__simdf_add1( tot, tot, t ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store1( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#define stbir__4_coeff_start() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc + (ofs) ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load1z( c, hc + (ofs) ); \ + stbir__simdf_load1( d, decode + (ofs) ); \ + stbir__simdf_madd( tot, tot, d, c ); } + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load2z( c, hc+(ofs) ); \ + stbir__simdf_load2( d, decode+(ofs) ); \ + stbir__simdf_madd( tot, tot, d, c ); } + +#define stbir__3_coeff_setup() \ + stbir__simdf mask; \ + stbir__simdf_load( mask, STBIR_mask + 3 ); + +#define stbir__3_coeff_remnant( ofs ) \ + stbir__simdf_load( c, hc+(ofs) ); \ + stbir__simdf_and( c, c, mask ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + +#define stbir__store_output() \ + stbir__simdf_0123to2301( c, tot ); \ + stbir__simdf_add( tot, tot, c ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_add1( tot, tot, c ); \ + stbir__simdf_store1( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#else + +#define stbir__1_coeff_only() \ + float tot; \ + tot = decode[0]*hc[0]; + +#define stbir__2_coeff_only() \ + float tot; \ + tot = decode[0] * hc[0]; \ + tot += decode[1] * hc[1]; + +#define stbir__3_coeff_only() \ + float tot; \ + tot = decode[0] * hc[0]; \ + tot += decode[1] * hc[1]; \ + tot += decode[2] * hc[2]; + +#define stbir__store_output_tiny() \ + output[0] = tot; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#define stbir__4_coeff_start() \ + float tot0,tot1,tot2,tot3; \ + tot0 = decode[0] * hc[0]; \ + tot1 = decode[1] * hc[1]; \ + tot2 = decode[2] * hc[2]; \ + tot3 = decode[3] * hc[3]; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; \ + tot3 += decode[3+(ofs)] * hc[3+(ofs)]; + +#define stbir__1_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; + +#define stbir__2_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + +#define stbir__3_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; + +#define stbir__store_output() \ + output[0] = (tot0+tot2)+(tot1+tot3); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#endif + +#define STBIR__horizontal_channels 1 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +//================= +// Do 2 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc ); \ + stbir__simdf_0123to0011( c, c ); \ + stbir__simdf_load2( d, decode ); \ + stbir__simdf_mult( tot, d, c ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( c, hc ); \ + stbir__simdf_0123to0011( c, c ); \ + stbir__simdf_mult_mem( tot, c, decode ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,cs,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load2z( d, decode+4 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__store_output_tiny() \ + stbir__simdf_0123to2301( c, tot ); \ + stbir__simdf_add( tot, tot, c ); \ + stbir__simdf_store2( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf t,d; \ + stbir__simdf_load1z( t, hc + (ofs) ); \ + stbir__simdf_load2( d, decode + (ofs) * 2 ); \ + stbir__simdf_0123to0011( t, t ); \ + stbir__simdf_mult( t, t, d ); \ + stbir__simdf8_add4( tot0, tot0, t ); } + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf t; \ + stbir__simdf_load2( t, hc + (ofs) ); \ + stbir__simdf_0123to0011( t, t ); \ + stbir__simdf_mult_mem( t, t, decode+(ofs)*2 ); \ + stbir__simdf8_add4( tot0, tot0, t ); } + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf8 d; \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_load6z( d, decode+(ofs)*2 ); \ + stbir__simdf8_madd( tot0, tot0, c, d ); } + +#define stbir__store_output() \ + { stbir__simdf t,d; \ + stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ + stbir__simdf_0123to2301( d, t ); \ + stbir__simdf_add( t, t, d ); \ + stbir__simdf_store2( output, t ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; } + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to2233( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ + stbir__simdf_0123to2233( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load1z( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_load2( d, decode + (ofs) * 2 ); \ + stbir__simdf_madd( tot0, tot0, d, c ); } + +#define stbir__2_coeff_remnant( ofs ) \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load2z( d, decode + (ofs) * 2 + 4 ); \ + stbir__simdf_madd( tot1, tot1, d, c ); } + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot1 ); \ + stbir__simdf_0123to2301( c, tot0 ); \ + stbir__simdf_add( tot0, tot0, c ); \ + stbir__simdf_store2( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; + +#define stbir__2_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; \ + c = hc[1]; \ + tota += decode[2]*c; \ + totb += decode[3]*c; + +// this weird order of add matches the simd +#define stbir__3_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; \ + c = hc[2]; \ + tota += decode[4]*c; \ + totb += decode[5]*c; \ + c = hc[1]; \ + tota += decode[2]*c; \ + totb += decode[3]*c; + +#define stbir__store_output_tiny() \ + output[0] = tota; \ + output[1] = totb; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#define stbir__4_coeff_start() \ + float tota0,tota1,tota2,tota3,totb0,totb1,totb2,totb3,c; \ + c = hc[0]; \ + tota0 = decode[0]*c; \ + totb0 = decode[1]*c; \ + c = hc[1]; \ + tota1 = decode[2]*c; \ + totb1 = decode[3]*c; \ + c = hc[2]; \ + tota2 = decode[4]*c; \ + totb2 = decode[5]*c; \ + c = hc[3]; \ + tota3 = decode[6]*c; \ + totb3 = decode[7]*c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2]*c; \ + totb0 += decode[1+(ofs)*2]*c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2]*c; \ + totb1 += decode[3+(ofs)*2]*c; \ + c = hc[2+(ofs)]; \ + tota2 += decode[4+(ofs)*2]*c; \ + totb2 += decode[5+(ofs)*2]*c; \ + c = hc[3+(ofs)]; \ + tota3 += decode[6+(ofs)*2]*c; \ + totb3 += decode[7+(ofs)*2]*c; + +#define stbir__1_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; + +#define stbir__2_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2] * c; \ + totb1 += decode[3+(ofs)*2] * c; + +#define stbir__3_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2] * c; \ + totb1 += decode[3+(ofs)*2] * c; \ + c = hc[2+(ofs)]; \ + tota2 += decode[4+(ofs)*2] * c; \ + totb2 += decode[5+(ofs)*2] * c; + +#define stbir__store_output() \ + output[0] = (tota0+tota2)+(tota1+tota3); \ + output[1] = (totb0+totb2)+(totb1+totb3); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#endif + +#define STBIR__horizontal_channels 2 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +//================= +// Do 3 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc ); \ + stbir__simdf_0123to0001( c, c ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,cs,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_load( d, decode+3 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,d,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_load( d, decode+3 ); \ + stbir__simdf_madd( tot, tot, d, c ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load( d, decode+6 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store2( output, tot ); \ + stbir__simdf_0123to2301( tot, tot ); \ + stbir__simdf_store1( output+2, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#ifdef STBIR_SIMD8 + +// we're loading from the XXXYYY decode by -1 to get the XXXYYY into different halves of the AVX reg fyi +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,tot1,c,cs; stbir__simdf t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode - 1 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1rep4( t, hc + (ofs) ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); + + #define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ + stbir__simdf8_0123to2222( t, cs ); \ + stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 ); + +#define stbir__store_output() \ + stbir__simdf8_add( tot0, tot0, tot1 ); \ + stbir__simdf_0123to1230( t, stbir__if_simdf8_cast_to_simdf4( tot0 ) ); \ + stbir__simdf8_add4halves( t, t, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; \ + if ( output < output_end ) \ + { \ + stbir__simdf_store( output-3, t ); \ + continue; \ + } \ + { stbir__simdf tt; stbir__simdf_0123to2301( tt, t ); \ + stbir__simdf_store2( output-3, t ); \ + stbir__simdf_store1( output+2-3, tt ); } \ + break; + + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,tot2,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); \ + stbir__simdf_0123to2333( c, cs ); \ + stbir__simdf_mult_mem( tot2, c, decode+8 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ + stbir__simdf_0123to2333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2z( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_load2z( d, decode+(ofs)*3+4 ); \ + stbir__simdf_madd( tot1, tot1, c, d ); } + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load1z( d, decode+(ofs)*3+8 ); \ + stbir__simdf_madd( tot2, tot2, c, d ); } + +#define stbir__store_output() \ + stbir__simdf_0123ABCDto3ABx( c, tot0, tot1 ); \ + stbir__simdf_0123ABCDto23Ax( cs, tot1, tot2 ); \ + stbir__simdf_0123to1230( tot2, tot2 ); \ + stbir__simdf_add( tot0, tot0, cs ); \ + stbir__simdf_add( c, c, tot2 ); \ + stbir__simdf_add( tot0, tot0, c ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; \ + if ( output < output_end ) \ + { \ + stbir__simdf_store( output-3, tot0 ); \ + continue; \ + } \ + stbir__simdf_0123to2301( tot1, tot0 ); \ + stbir__simdf_store2( output-3, tot0 ); \ + stbir__simdf_store1( output+2-3, tot1 ); \ + break; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; + +#define stbir__2_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + c = hc[1]; \ + tot0 += decode[3]*c; \ + tot1 += decode[4]*c; \ + tot2 += decode[5]*c; + +#define stbir__3_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + c = hc[1]; \ + tot0 += decode[3]*c; \ + tot1 += decode[4]*c; \ + tot2 += decode[5]*c; \ + c = hc[2]; \ + tot0 += decode[6]*c; \ + tot1 += decode[7]*c; \ + tot2 += decode[8]*c; + +#define stbir__store_output_tiny() \ + output[0] = tot0; \ + output[1] = tot1; \ + output[2] = tot2; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#define stbir__4_coeff_start() \ + float tota0,tota1,tota2,totb0,totb1,totb2,totc0,totc1,totc2,totd0,totd1,totd2,c; \ + c = hc[0]; \ + tota0 = decode[0]*c; \ + tota1 = decode[1]*c; \ + tota2 = decode[2]*c; \ + c = hc[1]; \ + totb0 = decode[3]*c; \ + totb1 = decode[4]*c; \ + totb2 = decode[5]*c; \ + c = hc[2]; \ + totc0 = decode[6]*c; \ + totc1 = decode[7]*c; \ + totc2 = decode[8]*c; \ + c = hc[3]; \ + totd0 = decode[9]*c; \ + totd1 = decode[10]*c; \ + totd2 = decode[11]*c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + c = hc[2+(ofs)]; \ + totc0 += decode[6+(ofs)*3]*c; \ + totc1 += decode[7+(ofs)*3]*c; \ + totc2 += decode[8+(ofs)*3]*c; \ + c = hc[3+(ofs)]; \ + totd0 += decode[9+(ofs)*3]*c; \ + totd1 += decode[10+(ofs)*3]*c; \ + totd2 += decode[11+(ofs)*3]*c; + +#define stbir__1_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; + +#define stbir__2_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + +#define stbir__3_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + c = hc[2+(ofs)]; \ + totc0 += decode[6+(ofs)*3]*c; \ + totc1 += decode[7+(ofs)*3]*c; \ + totc2 += decode[8+(ofs)*3]*c; + +#define stbir__store_output() \ + output[0] = (tota0+totc0)+(totb0+totd0); \ + output[1] = (tota1+totc1)+(totb1+totd1); \ + output[2] = (tota2+totc2)+(totb2+totd2); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#endif + +#define STBIR__horizontal_channels 3 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + +//================= +// Do 4 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_mult_mem( tot, c, decode ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+8 ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,c,cs; stbir__simdf t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1rep4( t, hc + (ofs) ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + + #define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf8_0123to2222( t, cs ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 ); + +#define stbir__store_output() \ + stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ + stbir__simdf_store( output, t ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+8 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+12 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; + +#define stbir__2_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; \ + c = hc[1]; \ + p0 += decode[4] * c; \ + p1 += decode[5] * c; \ + p2 += decode[6] * c; \ + p3 += decode[7] * c; + +#define stbir__3_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; \ + c = hc[1]; \ + p0 += decode[4] * c; \ + p1 += decode[5] * c; \ + p2 += decode[6] * c; \ + p3 += decode[7] * c; \ + c = hc[2]; \ + p0 += decode[8] * c; \ + p1 += decode[9] * c; \ + p2 += decode[10] * c; \ + p3 += decode[11] * c; + +#define stbir__store_output_tiny() \ + output[0] = p0; \ + output[1] = p1; \ + output[2] = p2; \ + output[3] = p3; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#define stbir__4_coeff_start() \ + float x0,x1,x2,x3,y0,y1,y2,y3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + x0 = decode[0] * c; \ + x1 = decode[1] * c; \ + x2 = decode[2] * c; \ + x3 = decode[3] * c; \ + c = hc[1]; \ + y0 = decode[4] * c; \ + y1 = decode[5] * c; \ + y2 = decode[6] * c; \ + y3 = decode[7] * c; \ + c = hc[2]; \ + x0 += decode[8] * c; \ + x1 += decode[9] * c; \ + x2 += decode[10] * c; \ + x3 += decode[11] * c; \ + c = hc[3]; \ + y0 += decode[12] * c; \ + y1 += decode[13] * c; \ + y2 += decode[14] * c; \ + y3 += decode[15] * c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[8+(ofs)*4] * c; \ + x1 += decode[9+(ofs)*4] * c; \ + x2 += decode[10+(ofs)*4] * c; \ + x3 += decode[11+(ofs)*4] * c; \ + c = hc[3+(ofs)]; \ + y0 += decode[12+(ofs)*4] * c; \ + y1 += decode[13+(ofs)*4] * c; \ + y2 += decode[14+(ofs)*4] * c; \ + y3 += decode[15+(ofs)*4] * c; + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[8+(ofs)*4] * c; \ + x1 += decode[9+(ofs)*4] * c; \ + x2 += decode[10+(ofs)*4] * c; \ + x3 += decode[11+(ofs)*4] * c; + +#define stbir__store_output() \ + output[0] = x0 + y0; \ + output[1] = x1 + y1; \ + output[2] = x2 + y2; \ + output[3] = x3 + y3; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#endif + +#define STBIR__horizontal_channels 4 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + + +//================= +// Do 7 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot0,tot1,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c,decode+10 ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store( output+3, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_mult_mem( tot1, c, decode+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf8_0123to33333333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf8_0123to33333333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load1b( c, hc + (ofs) ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load1b( c, hc + (ofs) ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_load1b( c, hc + (ofs)+1 ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); + +#define stbir__store_output() \ + stbir__simdf8_add( tot0, tot0, tot1 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; \ + if ( output < output_end ) \ + { \ + stbir__simdf8_store( output-7, tot0 ); \ + continue; \ + } \ + stbir__simdf_store( output-7+3, stbir__simdf_swiz(stbir__simdf8_gettop4(tot0),0,0,1,2) ); \ + stbir__simdf_store( output-7, stbir__if_simdf8_cast_to_simdf4(tot0) ); \ + break; + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,tot2,tot3,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_mult_mem( tot2, c, decode+7 ); \ + stbir__simdf_mult_mem( tot3, c, decode+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+21 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+24 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+21 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot2 ); \ + stbir__simdf_add( tot1, tot1, tot3 ); \ + stbir__simdf_store( output+3, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; + +#define stbir__2_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; \ + c = hc[1]; \ + tot0 += decode[7]*c; \ + tot1 += decode[8]*c; \ + tot2 += decode[9]*c; \ + tot3 += decode[10]*c; \ + tot4 += decode[11]*c; \ + tot5 += decode[12]*c; \ + tot6 += decode[13]*c; \ + +#define stbir__3_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; \ + c = hc[1]; \ + tot0 += decode[7]*c; \ + tot1 += decode[8]*c; \ + tot2 += decode[9]*c; \ + tot3 += decode[10]*c; \ + tot4 += decode[11]*c; \ + tot5 += decode[12]*c; \ + tot6 += decode[13]*c; \ + c = hc[2]; \ + tot0 += decode[14]*c; \ + tot1 += decode[15]*c; \ + tot2 += decode[16]*c; \ + tot3 += decode[17]*c; \ + tot4 += decode[18]*c; \ + tot5 += decode[19]*c; \ + tot6 += decode[20]*c; \ + +#define stbir__store_output_tiny() \ + output[0] = tot0; \ + output[1] = tot1; \ + output[2] = tot2; \ + output[3] = tot3; \ + output[4] = tot4; \ + output[5] = tot5; \ + output[6] = tot6; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#define stbir__4_coeff_start() \ + float x0,x1,x2,x3,x4,x5,x6,y0,y1,y2,y3,y4,y5,y6,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + x0 = decode[0] * c; \ + x1 = decode[1] * c; \ + x2 = decode[2] * c; \ + x3 = decode[3] * c; \ + x4 = decode[4] * c; \ + x5 = decode[5] * c; \ + x6 = decode[6] * c; \ + c = hc[1]; \ + y0 = decode[7] * c; \ + y1 = decode[8] * c; \ + y2 = decode[9] * c; \ + y3 = decode[10] * c; \ + y4 = decode[11] * c; \ + y5 = decode[12] * c; \ + y6 = decode[13] * c; \ + c = hc[2]; \ + x0 += decode[14] * c; \ + x1 += decode[15] * c; \ + x2 += decode[16] * c; \ + x3 += decode[17] * c; \ + x4 += decode[18] * c; \ + x5 += decode[19] * c; \ + x6 += decode[20] * c; \ + c = hc[3]; \ + y0 += decode[21] * c; \ + y1 += decode[22] * c; \ + y2 += decode[23] * c; \ + y3 += decode[24] * c; \ + y4 += decode[25] * c; \ + y5 += decode[26] * c; \ + y6 += decode[27] * c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[14+(ofs)*7] * c; \ + x1 += decode[15+(ofs)*7] * c; \ + x2 += decode[16+(ofs)*7] * c; \ + x3 += decode[17+(ofs)*7] * c; \ + x4 += decode[18+(ofs)*7] * c; \ + x5 += decode[19+(ofs)*7] * c; \ + x6 += decode[20+(ofs)*7] * c; \ + c = hc[3+(ofs)]; \ + y0 += decode[21+(ofs)*7] * c; \ + y1 += decode[22+(ofs)*7] * c; \ + y2 += decode[23+(ofs)*7] * c; \ + y3 += decode[24+(ofs)*7] * c; \ + y4 += decode[25+(ofs)*7] * c; \ + y5 += decode[26+(ofs)*7] * c; \ + y6 += decode[27+(ofs)*7] * c; + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[14+(ofs)*7] * c; \ + x1 += decode[15+(ofs)*7] * c; \ + x2 += decode[16+(ofs)*7] * c; \ + x3 += decode[17+(ofs)*7] * c; \ + x4 += decode[18+(ofs)*7] * c; \ + x5 += decode[19+(ofs)*7] * c; \ + x6 += decode[20+(ofs)*7] * c; \ + +#define stbir__store_output() \ + output[0] = x0 + y0; \ + output[1] = x1 + y1; \ + output[2] = x2 + y2; \ + output[3] = x3 + y3; \ + output[4] = x4 + y4; \ + output[5] = x5 + y5; \ + output[6] = x6 + y6; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#endif + +#define STBIR__horizontal_channels 7 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +// include all of the vertical resamplers (both scatter and gather versions) + +#define STBIR__vertical_channels 1 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 1 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 2 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 2 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 3 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 3 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 4 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 4 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 5 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 5 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 6 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 6 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 7 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 7 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 8 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 8 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +typedef void STBIR_VERTICAL_GATHERFUNC( float * output, float const * coeffs, float const ** inputs, float const * input0_end ); + +static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers[ 8 ] = +{ + stbir__vertical_gather_with_1_coeffs,stbir__vertical_gather_with_2_coeffs,stbir__vertical_gather_with_3_coeffs,stbir__vertical_gather_with_4_coeffs,stbir__vertical_gather_with_5_coeffs,stbir__vertical_gather_with_6_coeffs,stbir__vertical_gather_with_7_coeffs,stbir__vertical_gather_with_8_coeffs +}; + +static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers_continues[ 8 ] = +{ + stbir__vertical_gather_with_1_coeffs_cont,stbir__vertical_gather_with_2_coeffs_cont,stbir__vertical_gather_with_3_coeffs_cont,stbir__vertical_gather_with_4_coeffs_cont,stbir__vertical_gather_with_5_coeffs_cont,stbir__vertical_gather_with_6_coeffs_cont,stbir__vertical_gather_with_7_coeffs_cont,stbir__vertical_gather_with_8_coeffs_cont +}; + +typedef void STBIR_VERTICAL_SCATTERFUNC( float ** outputs, float const * coeffs, float const * input, float const * input_end ); + +static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_sets[ 8 ] = +{ + stbir__vertical_scatter_with_1_coeffs,stbir__vertical_scatter_with_2_coeffs,stbir__vertical_scatter_with_3_coeffs,stbir__vertical_scatter_with_4_coeffs,stbir__vertical_scatter_with_5_coeffs,stbir__vertical_scatter_with_6_coeffs,stbir__vertical_scatter_with_7_coeffs,stbir__vertical_scatter_with_8_coeffs +}; + +static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_blends[ 8 ] = +{ + stbir__vertical_scatter_with_1_coeffs_cont,stbir__vertical_scatter_with_2_coeffs_cont,stbir__vertical_scatter_with_3_coeffs_cont,stbir__vertical_scatter_with_4_coeffs_cont,stbir__vertical_scatter_with_5_coeffs_cont,stbir__vertical_scatter_with_6_coeffs_cont,stbir__vertical_scatter_with_7_coeffs_cont,stbir__vertical_scatter_with_8_coeffs_cont +}; + + +static void stbir__encode_scanline( stbir__info const * stbir_info, void *output_buffer_data, float * encode_buffer, int row STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + int num_pixels = stbir_info->horizontal.scale_info.output_sub_size; + int channels = stbir_info->channels; + int width_times_channels = num_pixels * channels; + void * output_buffer; + + // un-alpha weight if we need to + if ( stbir_info->alpha_unweight ) + { + STBIR_PROFILE_START( unalpha ); + stbir_info->alpha_unweight( encode_buffer, width_times_channels ); + STBIR_PROFILE_END( unalpha ); + } + + // write directly into output by default + output_buffer = output_buffer_data; + + // if we have an output callback, we first convert the decode buffer in place (and then hand that to the callback) + if ( stbir_info->out_pixels_cb ) + output_buffer = encode_buffer; + + STBIR_PROFILE_START( encode ); + // convert into the output buffer + stbir_info->encode_pixels( output_buffer, width_times_channels, encode_buffer ); + STBIR_PROFILE_END( encode ); + + // if we have an output callback, call it to send the data + if ( stbir_info->out_pixels_cb ) + stbir_info->out_pixels_cb( output_buffer, num_pixels, row, stbir_info->user_data ); +} + + +// Get the ring buffer pointer for an index +static float* stbir__get_ring_buffer_entry(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int index ) +{ + STBIR_ASSERT( index < stbir_info->ring_buffer_num_entries ); + + #ifdef STBIR__SEPARATE_ALLOCATIONS + return split_info->ring_buffers[ index ]; + #else + return (float*) ( ( (char*) split_info->ring_buffer ) + ( index * stbir_info->ring_buffer_length_bytes ) ); + #endif +} + +// Get the specified scan line from the ring buffer +static float* stbir__get_ring_buffer_scanline(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int get_scanline) +{ + int ring_buffer_index = (split_info->ring_buffer_begin_index + (get_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + return stbir__get_ring_buffer_entry( stbir_info, split_info, ring_buffer_index ); +} + +static void stbir__resample_horizontal_gather(stbir__info const * stbir_info, float* output_buffer, float const * input_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + float const * decode_buffer = input_buffer - ( stbir_info->scanline_extents.conservative.n0 * stbir_info->effective_channels ); + + STBIR_PROFILE_START( horizontal ); + if ( ( stbir_info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( stbir_info->horizontal.scale_info.scale == 1.0f ) ) + STBIR_MEMCPY( output_buffer, input_buffer, stbir_info->horizontal.scale_info.output_sub_size * sizeof( float ) * stbir_info->effective_channels ); + else + stbir_info->horizontal_gather_channels( output_buffer, stbir_info->horizontal.scale_info.output_sub_size, decode_buffer, stbir_info->horizontal.contributors, stbir_info->horizontal.coefficients, stbir_info->horizontal.coefficient_width ); + STBIR_PROFILE_END( horizontal ); +} + +static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n, int contrib_n0, int contrib_n1, float const * vertical_coefficients ) +{ + float* encode_buffer = split_info->vertical_buffer; + float* decode_buffer = split_info->decode_buffer; + int vertical_first = stbir_info->vertical_first; + int width = (vertical_first) ? ( stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1 ) : stbir_info->horizontal.scale_info.output_sub_size; + int width_times_channels = stbir_info->effective_channels * width; + + STBIR_ASSERT( stbir_info->vertical.is_gather ); + + // loop over the contributing scanlines and scale into the buffer + STBIR_PROFILE_START( vertical ); + { + int k = 0, total = contrib_n1 - contrib_n0 + 1; + STBIR_ASSERT( total > 0 ); + do { + float const * inputs[8]; + int i, cnt = total; if ( cnt > 8 ) cnt = 8; + for( i = 0 ; i < cnt ; i++ ) + inputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+contrib_n0 ); + + // call the N scanlines at a time function (up to 8 scanlines of blending at once) + ((k==0)?stbir__vertical_gathers:stbir__vertical_gathers_continues)[cnt-1]( (vertical_first) ? decode_buffer : encode_buffer, vertical_coefficients + k, inputs, inputs[0] + width_times_channels ); + k += cnt; + total -= cnt; + } while ( total ); + } + STBIR_PROFILE_END( vertical ); + + if ( vertical_first ) + { + // Now resample the gathered vertical data in the horizontal axis into the encode buffer + stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + } + + stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((size_t)n * (size_t)stbir_info->output_stride_bytes), + encode_buffer, n STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); +} + +static void stbir__decode_and_resample_for_vertical_gather_loop(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, n, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // update new end scanline + split_info->ring_buffer_last_scanline = n; + + // get ring buffer + ring_buffer_index = (split_info->ring_buffer_begin_index + (split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + ring_buffer = stbir__get_ring_buffer_entry(stbir_info, split_info, ring_buffer_index); + + // Now resample it into the ring buffer. + stbir__resample_horizontal_gather( stbir_info, ring_buffer, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) +{ + int y, start_output_y, end_output_y; + stbir__contributors* vertical_contributors = stbir_info->vertical.contributors; + float const * vertical_coefficients = stbir_info->vertical.coefficients; + + STBIR_ASSERT( stbir_info->vertical.is_gather ); + + start_output_y = split_info->start_output_y; + end_output_y = split_info[split_count-1].end_output_y; + + vertical_contributors += start_output_y; + vertical_coefficients += start_output_y * stbir_info->vertical.coefficient_width; + + // initialize the ring buffer for gathering + split_info->ring_buffer_begin_index = 0; + split_info->ring_buffer_first_scanline = vertical_contributors->n0; + split_info->ring_buffer_last_scanline = split_info->ring_buffer_first_scanline - 1; // means "empty" + + for (y = start_output_y; y < end_output_y; y++) + { + int in_first_scanline, in_last_scanline; + + in_first_scanline = vertical_contributors->n0; + in_last_scanline = vertical_contributors->n1; + + // make sure the indexing hasn't broken + STBIR_ASSERT( in_first_scanline >= split_info->ring_buffer_first_scanline ); + + // Load in new scanlines + while (in_last_scanline > split_info->ring_buffer_last_scanline) + { + STBIR_ASSERT( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) <= stbir_info->ring_buffer_num_entries ); + + // make sure there was room in the ring buffer when we add new scanlines + if ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) + { + split_info->ring_buffer_first_scanline++; + split_info->ring_buffer_begin_index++; + } + + if ( stbir_info->vertical_first ) + { + float * ring_buffer = stbir__get_ring_buffer_scanline( stbir_info, split_info, ++split_info->ring_buffer_last_scanline ); + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + } + else + { + stbir__decode_and_resample_for_vertical_gather_loop(stbir_info, split_info, split_info->ring_buffer_last_scanline + 1); + } + } + + // Now all buffers should be ready to write a row of vertical sampling, so do it. + stbir__resample_vertical_gather(stbir_info, split_info, y, in_first_scanline, in_last_scanline, vertical_coefficients ); + + ++vertical_contributors; + vertical_coefficients += stbir_info->vertical.coefficient_width; + } +} + +#define STBIR__FLOAT_EMPTY_MARKER 3.0e+38F +#define STBIR__FLOAT_BUFFER_IS_EMPTY(ptr) ((ptr)[0]==STBIR__FLOAT_EMPTY_MARKER) + +static void stbir__encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info) +{ + // evict a scanline out into the output buffer + float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); + + // dump the scanline out + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // mark it as empty + ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; + + // advance the first scanline + split_info->ring_buffer_first_scanline++; + if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries ) + split_info->ring_buffer_begin_index = 0; +} + +static void stbir__horizontal_resample_and_encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info) +{ + // evict a scanline out into the output buffer + + float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); + + // Now resample it into the buffer. + stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, ring_buffer_entry STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // dump the scanline out + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // mark it as empty + ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; + + // advance the first scanline + split_info->ring_buffer_first_scanline++; + if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries ) + split_info->ring_buffer_begin_index = 0; +} + +static void stbir__resample_vertical_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n0, int n1, float const * vertical_coefficients, float const * vertical_buffer, float const * vertical_buffer_end ) +{ + STBIR_ASSERT( !stbir_info->vertical.is_gather ); + + STBIR_PROFILE_START( vertical ); + { + int k = 0, total = n1 - n0 + 1; + STBIR_ASSERT( total > 0 ); + do { + float * outputs[8]; + int i, n = total; if ( n > 8 ) n = 8; + for( i = 0 ; i < n ; i++ ) + { + outputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+n0 ); + if ( ( i ) && ( STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[i] ) != STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ) ) ) // make sure runs are of the same type + { + n = i; + break; + } + } + // call the scatter to N scanlines at a time function (up to 8 scanlines of scattering at once) + ((STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ))?stbir__vertical_scatter_sets:stbir__vertical_scatter_blends)[n-1]( outputs, vertical_coefficients + k, vertical_buffer, vertical_buffer_end ); + k += n; + total -= n; + } while ( total ); + } + + STBIR_PROFILE_END( vertical ); +} + +typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info); + +static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) +{ + int y, start_output_y, end_output_y, start_input_y, end_input_y; + stbir__contributors* vertical_contributors = stbir_info->vertical.contributors; + float const * vertical_coefficients = stbir_info->vertical.coefficients; + stbir__handle_scanline_for_scatter_func * handle_scanline_for_scatter; + void * scanline_scatter_buffer; + void * scanline_scatter_buffer_end; + int on_first_input_y, last_input_y; + + STBIR_ASSERT( !stbir_info->vertical.is_gather ); + + start_output_y = split_info->start_output_y; + end_output_y = split_info[split_count-1].end_output_y; // may do multiple split counts + + start_input_y = split_info->start_input_y; + end_input_y = split_info[split_count-1].end_input_y; + + // adjust for starting offset start_input_y + y = start_input_y + stbir_info->vertical.filter_pixel_margin; + vertical_contributors += y ; + vertical_coefficients += stbir_info->vertical.coefficient_width * y; + + if ( stbir_info->vertical_first ) + { + handle_scanline_for_scatter = stbir__horizontal_resample_and_encode_first_scanline_from_scatter; + scanline_scatter_buffer = split_info->decode_buffer; + scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * (stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1); + } + else + { + handle_scanline_for_scatter = stbir__encode_first_scanline_from_scatter; + scanline_scatter_buffer = split_info->vertical_buffer; + scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * stbir_info->horizontal.scale_info.output_sub_size; + } + + // initialize the ring buffer for scattering + split_info->ring_buffer_first_scanline = start_output_y; + split_info->ring_buffer_last_scanline = -1; + split_info->ring_buffer_begin_index = -1; + + // mark all the buffers as empty to start + for( y = 0 ; y < stbir_info->ring_buffer_num_entries ; y++ ) + stbir__get_ring_buffer_entry( stbir_info, split_info, y )[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter + + // do the loop in input space + on_first_input_y = 1; last_input_y = start_input_y; + for (y = start_input_y ; y < end_input_y; y++) + { + int out_first_scanline, out_last_scanline; + + out_first_scanline = vertical_contributors->n0; + out_last_scanline = vertical_contributors->n1; + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if ( ( out_last_scanline >= out_first_scanline ) && ( ( ( out_first_scanline >= start_output_y ) && ( out_first_scanline < end_output_y ) ) || ( ( out_last_scanline >= start_output_y ) && ( out_last_scanline < end_output_y ) ) ) ) + { + float const * vc = vertical_coefficients; + + // keep track of the range actually seen for the next resize + last_input_y = y; + if ( ( on_first_input_y ) && ( y > start_input_y ) ) + split_info->start_input_y = y; + on_first_input_y = 0; + + // clip the region + if ( out_first_scanline < start_output_y ) + { + vc += start_output_y - out_first_scanline; + out_first_scanline = start_output_y; + } + + if ( out_last_scanline >= end_output_y ) + out_last_scanline = end_output_y - 1; + + // if very first scanline, init the index + if (split_info->ring_buffer_begin_index < 0) + split_info->ring_buffer_begin_index = out_first_scanline - start_output_y; + + STBIR_ASSERT( split_info->ring_buffer_begin_index <= out_first_scanline ); + + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, y, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // When horizontal first, we resample horizontally into the vertical buffer before we scatter it out + if ( !stbir_info->vertical_first ) + stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // Now it's sitting in the buffer ready to be distributed into the ring buffers. + + // evict from the ringbuffer, if we need are full + if ( ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) && + ( out_last_scanline > split_info->ring_buffer_last_scanline ) ) + handle_scanline_for_scatter( stbir_info, split_info ); + + // Now the horizontal buffer is ready to write to all ring buffer rows, so do it. + stbir__resample_vertical_scatter(stbir_info, split_info, out_first_scanline, out_last_scanline, vc, (float*)scanline_scatter_buffer, (float*)scanline_scatter_buffer_end ); + + // update the end of the buffer + if ( out_last_scanline > split_info->ring_buffer_last_scanline ) + split_info->ring_buffer_last_scanline = out_last_scanline; + } + ++vertical_contributors; + vertical_coefficients += stbir_info->vertical.coefficient_width; + } + + // now evict the scanlines that are left over in the ring buffer + while ( split_info->ring_buffer_first_scanline < end_output_y ) + handle_scanline_for_scatter(stbir_info, split_info); + + // update the end_input_y if we do multiple resizes with the same data + ++last_input_y; + for( y = 0 ; y < split_count; y++ ) + if ( split_info[y].end_input_y > last_input_y ) + split_info[y].end_input_y = last_input_y; +} + + +static stbir__kernel_callback * stbir__builtin_kernels[] = { 0, stbir__filter_trapezoid, stbir__filter_triangle, stbir__filter_cubic, stbir__filter_catmullrom, stbir__filter_mitchell, stbir__filter_point }; +static stbir__support_callback * stbir__builtin_supports[] = { 0, stbir__support_trapezoid, stbir__support_one, stbir__support_two, stbir__support_two, stbir__support_two, stbir__support_zeropoint5 }; + +static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir__kernel_callback * kernel, stbir__support_callback * support, stbir_edge edge, stbir__scale_info * scale_info, int always_gather, void * user_data ) +{ + // set filter + if (filter == 0) + { + filter = STBIR_DEFAULT_FILTER_DOWNSAMPLE; // default to downsample + if (scale_info->scale >= ( 1.0f - stbir__small_float ) ) + { + if ( (scale_info->scale <= ( 1.0f + stbir__small_float ) ) && ( STBIR_CEILF(scale_info->pixel_shift) == scale_info->pixel_shift ) ) + filter = STBIR_FILTER_POINT_SAMPLE; + else + filter = STBIR_DEFAULT_FILTER_UPSAMPLE; + } + } + samp->filter_enum = filter; + + STBIR_ASSERT(samp->filter_enum != 0); + STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER); + samp->filter_kernel = stbir__builtin_kernels[ filter ]; + samp->filter_support = stbir__builtin_supports[ filter ]; + + if ( kernel && support ) + { + samp->filter_kernel = kernel; + samp->filter_support = support; + samp->filter_enum = STBIR_FILTER_OTHER; + } + + samp->edge = edge; + samp->filter_pixel_width = stbir__get_filter_pixel_width (samp->filter_support, scale_info->scale, user_data ); + // Gather is always better, but in extreme downsamples, you have to most or all of the data in memory + // For horizontal, we always have all the pixels, so we always use gather here (always_gather==1). + // For vertical, we use gather if scaling up (which means we will have samp->filter_pixel_width + // scanlines in memory at once). + samp->is_gather = 0; + if ( scale_info->scale >= ( 1.0f - stbir__small_float ) ) + samp->is_gather = 1; + else if ( ( always_gather ) || ( samp->filter_pixel_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT ) ) + samp->is_gather = 2; + + // pre calculate stuff based on the above + samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data); + + // filter_pixel_width is the conservative size in pixels of input that affect an output pixel. + // In rare cases (only with 2 pix to 1 pix with the default filters), it's possible that the + // filter will extend before or after the scanline beyond just one extra entire copy of the + // scanline (we would hit the edge twice). We don't let you do that, so we clamp the total + // width to 3x the total of input pixel (once for the scanline, once for the left side + // overhang, and once for the right side). We only do this for edge mode, since the other + // modes can just re-edge clamp back in again. + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_width > ( scale_info->input_full_size * 3 ) ) + samp->filter_pixel_width = scale_info->input_full_size * 3; + + // This is how much to expand buffers to account for filters seeking outside + // the image boundaries. + samp->filter_pixel_margin = samp->filter_pixel_width / 2; + + // filter_pixel_margin is the amount that this filter can overhang on just one side of either + // end of the scanline (left or the right). Since we only allow you to overhang 1 scanline's + // worth of pixels, we clamp this one side of overhang to the input scanline size. Again, + // this clamping only happens in rare cases with the default filters (2 pix to 1 pix). + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_margin > scale_info->input_full_size ) + samp->filter_pixel_margin = scale_info->input_full_size; + + samp->num_contributors = stbir__get_contributors(samp, samp->is_gather); + + samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors); + samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding + + samp->gather_prescatter_contributors = 0; + samp->gather_prescatter_coefficients = 0; + if ( samp->is_gather == 0 ) + { + samp->gather_prescatter_coefficient_width = samp->filter_pixel_width; + samp->gather_prescatter_num_contributors = stbir__get_contributors(samp, 2); + samp->gather_prescatter_contributors_size = samp->gather_prescatter_num_contributors * sizeof(stbir__contributors); + samp->gather_prescatter_coefficients_size = samp->gather_prescatter_num_contributors * samp->gather_prescatter_coefficient_width * sizeof(float); + } +} + +static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contributors * range, void * user_data ) +{ + float scale = samp->scale_info.scale; + float out_shift = samp->scale_info.pixel_shift; + stbir__support_callback * support = samp->filter_support; + int input_full_size = samp->scale_info.input_full_size; + stbir_edge edge = samp->edge; + float inv_scale = samp->scale_info.inv_scale; + + STBIR_ASSERT( samp->is_gather != 0 ); + + if ( samp->is_gather == 1 ) + { + int in_first_pixel, in_last_pixel; + float out_filter_radius = support(inv_scale, user_data) * scale; + + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0.5, out_filter_radius, inv_scale, out_shift, input_full_size, edge ); + range->n0 = in_first_pixel; + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, ( (float)(samp->scale_info.output_sub_size-1) ) + 0.5f, out_filter_radius, inv_scale, out_shift, input_full_size, edge ); + range->n1 = in_last_pixel; + } + else if ( samp->is_gather == 2 ) // downsample gather, refine + { + float in_pixels_radius = support(scale, user_data) * inv_scale; + int filter_pixel_margin = samp->filter_pixel_margin; + int output_sub_size = samp->scale_info.output_sub_size; + int input_end; + int n; + int in_first_pixel, in_last_pixel; + + // get a conservative area of the input range + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0, 0, inv_scale, out_shift, input_full_size, edge ); + range->n0 = in_first_pixel; + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, (float)output_sub_size, 0, inv_scale, out_shift, input_full_size, edge ); + range->n1 = in_last_pixel; + + // now go through the margin to the start of area to find bottom + n = range->n0 + 1; + input_end = -filter_pixel_margin; + while( n >= input_end ) + { + int out_first_pixel, out_last_pixel; + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size ); + if ( out_first_pixel > out_last_pixel ) + break; + + if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) ) + range->n0 = n; + --n; + } + + // now go through the end of the area through the margin to find top + n = range->n1 - 1; + input_end = n + 1 + filter_pixel_margin; + while( n <= input_end ) + { + int out_first_pixel, out_last_pixel; + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size ); + if ( out_first_pixel > out_last_pixel ) + break; + if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) ) + range->n1 = n; + ++n; + } + } + + if ( samp->edge == STBIR_EDGE_WRAP ) + { + // if we are wrapping, and we are very close to the image size (so the edges might merge), just use the scanline up to the edge + if ( ( range->n0 > 0 ) && ( range->n1 >= input_full_size ) ) + { + int marg = range->n1 - input_full_size + 1; + if ( ( marg + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= range->n0 ) + range->n0 = 0; + } + if ( ( range->n0 < 0 ) && ( range->n1 < (input_full_size-1) ) ) + { + int marg = -range->n0; + if ( ( input_full_size - marg - STBIR__MERGE_RUNS_PIXEL_THRESHOLD - 1 ) <= range->n1 ) + range->n1 = input_full_size - 1; + } + } + else + { + // for non-edge-wrap modes, we never read over the edge, so clamp + if ( range->n0 < 0 ) + range->n0 = 0; + if ( range->n1 >= input_full_size ) + range->n1 = input_full_size - 1; + } +} + +static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height ) +{ + int i, cur; + int left = output_height; + + cur = 0; + for( i = 0 ; i < splits ; i++ ) + { + int each; + split_info[i].start_output_y = cur; + each = left / ( splits - i ); + split_info[i].end_output_y = cur + each; + cur += each; + left -= each; + + // scatter range (updated to minimum as you run it) + split_info[i].start_input_y = -vertical_pixel_margin; + split_info[i].end_input_y = input_full_height + vertical_pixel_margin; + } +} + +static void stbir__free_internal_mem( stbir__info *info ) +{ + #define STBIR__FREE_AND_CLEAR( ptr ) { if ( ptr ) { void * p = (ptr); (ptr) = 0; STBIR_FREE( p, info->user_data); } } + + if ( info ) + { + #ifndef STBIR__SEPARATE_ALLOCATIONS + STBIR__FREE_AND_CLEAR( info->alloced_mem ); + #else + int i,j; + + if ( ( info->vertical.gather_prescatter_contributors ) && ( (void*)info->vertical.gather_prescatter_contributors != (void*)info->split_info[0].decode_buffer ) ) + { + STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_coefficients ); + STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_contributors ); + } + for( i = 0 ; i < info->splits ; i++ ) + { + for( j = 0 ; j < info->alloc_ring_buffer_num_entries ; j++ ) + { + #ifdef STBIR_SIMD8 + if ( info->effective_channels == 3 ) + --info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer + #endif + STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers[j] ); + } + + #ifdef STBIR_SIMD8 + if ( info->effective_channels == 3 ) + --info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer + #endif + STBIR__FREE_AND_CLEAR( info->split_info[i].decode_buffer ); + STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers ); + STBIR__FREE_AND_CLEAR( info->split_info[i].vertical_buffer ); + } + STBIR__FREE_AND_CLEAR( info->split_info ); + if ( info->vertical.coefficients != info->horizontal.coefficients ) + { + STBIR__FREE_AND_CLEAR( info->vertical.coefficients ); + STBIR__FREE_AND_CLEAR( info->vertical.contributors ); + } + STBIR__FREE_AND_CLEAR( info->horizontal.coefficients ); + STBIR__FREE_AND_CLEAR( info->horizontal.contributors ); + STBIR__FREE_AND_CLEAR( info->alloced_mem ); + STBIR_FREE( info, info->user_data ); + #endif + } + + #undef STBIR__FREE_AND_CLEAR +} + +static int stbir__get_max_split( int splits, int height ) +{ + int i; + int max = 0; + + for( i = 0 ; i < splits ; i++ ) + { + int each = height / ( splits - i ); + if ( each > max ) + max = each; + height -= each; + } + return max; +} + +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] = +{ + 0, stbir__horizontal_gather_1_channels_with_n_coeffs_funcs, stbir__horizontal_gather_2_channels_with_n_coeffs_funcs, stbir__horizontal_gather_3_channels_with_n_coeffs_funcs, stbir__horizontal_gather_4_channels_with_n_coeffs_funcs, 0,0, stbir__horizontal_gather_7_channels_with_n_coeffs_funcs +}; + +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] = +{ + 0, stbir__horizontal_gather_1_channels_funcs, stbir__horizontal_gather_2_channels_funcs, stbir__horizontal_gather_3_channels_funcs, stbir__horizontal_gather_4_channels_funcs, 0,0, stbir__horizontal_gather_7_channels_funcs +}; + +// there are six resize classifications: 0 == vertical scatter, 1 == vertical gather < 1x scale, 2 == vertical gather 1x-2x scale, 4 == vertical gather < 3x scale, 4 == vertical gather > 3x scale, 5 == <=4 pixel height, 6 == <=4 pixel wide column +#define STBIR_RESIZE_CLASSIFICATIONS 8 + +static float stbir__compute_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4]= // 5 = 0=1chan, 1=2chan, 2=3chan, 3=4chan, 4=7chan +{ + { + { 1.00000f, 1.00000f, 0.31250f, 1.00000f }, + { 0.56250f, 0.59375f, 0.00000f, 0.96875f }, + { 1.00000f, 0.06250f, 0.00000f, 1.00000f }, + { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.03125f }, + }, { + { 0.00000f, 0.84375f, 0.00000f, 0.03125f }, + { 0.09375f, 0.93750f, 0.00000f, 0.78125f }, + { 0.87500f, 0.21875f, 0.00000f, 0.96875f }, + { 0.09375f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.53125f }, + }, { + { 0.00000f, 0.53125f, 0.00000f, 0.03125f }, + { 0.06250f, 0.96875f, 0.00000f, 0.53125f }, + { 0.87500f, 0.18750f, 0.00000f, 0.93750f }, + { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.56250f }, + }, { + { 0.00000f, 0.50000f, 0.00000f, 0.71875f }, + { 0.06250f, 0.84375f, 0.00000f, 0.87500f }, + { 1.00000f, 0.50000f, 0.50000f, 0.96875f }, + { 1.00000f, 0.09375f, 0.31250f, 0.50000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 1.00000f, 0.03125f, 0.03125f, 0.53125f }, + { 0.18750f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.03125f, 0.18750f }, + }, { + { 0.00000f, 0.59375f, 0.00000f, 0.96875f }, + { 0.06250f, 0.81250f, 0.06250f, 0.59375f }, + { 0.75000f, 0.43750f, 0.12500f, 0.96875f }, + { 0.87500f, 0.06250f, 0.18750f, 0.43750f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.15625f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.03125f, 0.34375f }, + } +}; + +// structure that allow us to query and override info for training the costs +typedef struct STBIR__V_FIRST_INFO +{ + double v_cost, h_cost; + int control_v_first; // 0 = no control, 1 = force hori, 2 = force vert + int v_first; + int v_resize_classification; + int is_gather; +} STBIR__V_FIRST_INFO; + +#ifdef STBIR__V_FIRST_INFO_BUFFER +static STBIR__V_FIRST_INFO STBIR__V_FIRST_INFO_BUFFER = {0}; +#define STBIR__V_FIRST_INFO_POINTER &STBIR__V_FIRST_INFO_BUFFER +#else +#define STBIR__V_FIRST_INFO_POINTER 0 +#endif + +// Figure out whether to scale along the horizontal or vertical first. +// This only *super* important when you are scaling by a massively +// different amount in the vertical vs the horizontal (for example, if +// you are scaling by 2x in the width, and 0.5x in the height, then you +// want to do the vertical scale first, because it's around 3x faster +// in that order. +// +// In more normal circumstances, this makes a 20-40% differences, so +// it's good to get right, but not critical. The normal way that you +// decide which direction goes first is just figuring out which +// direction does more multiplies. But with modern CPUs with their +// fancy caches and SIMD and high IPC abilities, so there's just a lot +// more that goes into it. +// +// My handwavy sort of solution is to have an app that does a whole +// bunch of timing for both vertical and horizontal first modes, +// and then another app that can read lots of these timing files +// and try to search for the best weights to use. Dotimings.c +// is the app that does a bunch of timings, and vf_train.c is the +// app that solves for the best weights (and shows how well it +// does currently). + +static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info ) +{ + double v_cost, h_cost; + float * weights; + int vertical_first; + int v_classification; + + // categorize the resize into buckets + if ( ( vertical_output_size <= 4 ) || ( horizontal_output_size <= 4 ) ) + v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7; + else if ( vertical_scale <= 1.0f ) + v_classification = ( is_gather ) ? 1 : 0; + else if ( vertical_scale <= 2.0f) + v_classification = 2; + else if ( vertical_scale <= 3.0f) + v_classification = 3; + else if ( vertical_scale <= 4.0f) + v_classification = 5; + else + v_classification = 6; + + // use the right weights + weights = weights_table[ v_classification ]; + + // this is the costs when you don't take into account modern CPUs with high ipc and simd and caches - wish we had a better estimate + h_cost = (float)horizontal_filter_pixel_width * weights[0] + horizontal_scale * (float)vertical_filter_pixel_width * weights[1]; + v_cost = (float)vertical_filter_pixel_width * weights[2] + vertical_scale * (float)horizontal_filter_pixel_width * weights[3]; + + // use computation estimate to decide vertical first or not + vertical_first = ( v_cost <= h_cost ) ? 1 : 0; + + // save these, if requested + if ( info ) + { + info->h_cost = h_cost; + info->v_cost = v_cost; + info->v_resize_classification = v_classification; + info->v_first = vertical_first; + info->is_gather = is_gather; + } + + // and this allows us to override everything for testing (see dotiming.c) + if ( ( info ) && ( info->control_v_first ) ) + vertical_first = ( info->control_v_first == 2 ) ? 1 : 0; + + return vertical_first; +} + +// layout lookups - must match stbir_internal_pixel_layout +static unsigned char stbir__pixel_channels[] = { + 1,2,3,3,4, // 1ch, 2ch, rgb, bgr, 4ch + 4,4,4,4,2,2, // RGBA,BGRA,ARGB,ABGR,RA,AR + 4,4,4,4,2,2, // RGBA_PM,BGRA_PM,ARGB_PM,ABGR_PM,RA_PM,AR_PM +}; + +// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +static stbir_internal_pixel_layout stbir__pixel_layout_convert_public_to_internal[] = { + STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA, + STBIRI_4CHANNEL, STBIRI_BGRA, STBIRI_ARGB, STBIRI_ABGR, STBIRI_RA, STBIRI_AR, + STBIRI_RGBA_PM, STBIRI_BGRA_PM, STBIRI_ARGB_PM, STBIRI_ABGR_PM, STBIRI_RA_PM, STBIRI_AR_PM, +}; + +static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sampler * horizontal, stbir__sampler * vertical, stbir__contributors * conservative, stbir_pixel_layout input_pixel_layout_public, stbir_pixel_layout output_pixel_layout_public, int splits, int new_x, int new_y, int fast_alpha, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO ) +{ + static char stbir_channel_count_index[8]={ 9,0,1,2, 3,9,9,4 }; + + stbir__info * info = 0; + void * alloced = 0; + size_t alloced_total = 0; + int vertical_first; + int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries; + + int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy + int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); + stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ]; + stbir_internal_pixel_layout output_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ output_pixel_layout_public ]; + int channels = stbir__pixel_channels[ input_pixel_layout ]; + int effective_channels = channels; + + // first figure out what type of alpha weighting to use (if any) + if ( ( horizontal->filter_enum != STBIR_FILTER_POINT_SAMPLE ) || ( vertical->filter_enum != STBIR_FILTER_POINT_SAMPLE ) ) // no alpha weighting on point sampling + { + if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) ) + { + if ( fast_alpha ) + { + alpha_weighting_type = 4; + } + else + { + static int fancy_alpha_effective_cnts[6] = { 7, 7, 7, 7, 3, 3 }; + alpha_weighting_type = 2; + effective_channels = fancy_alpha_effective_cnts[ input_pixel_layout - STBIRI_RGBA ]; + } + } + else if ( ( input_pixel_layout >= STBIRI_RGBA_PM ) && ( input_pixel_layout <= STBIRI_AR_PM ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) ) + { + // input premult, output non-premult + alpha_weighting_type = 3; + } + else if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA_PM ) && ( output_pixel_layout <= STBIRI_AR_PM ) ) + { + // input non-premult, output premult + alpha_weighting_type = 1; + } + } + + // channel in and out count must match currently + if ( channels != stbir__pixel_channels[ output_pixel_layout ] ) + return 0; + + // get vertical first + vertical_first = stbir__should_do_vertical_first( stbir__compute_weights[ (int)stbir_channel_count_index[ effective_channels ] ], horizontal->filter_pixel_width, horizontal->scale_info.scale, horizontal->scale_info.output_sub_size, vertical->filter_pixel_width, vertical->scale_info.scale, vertical->scale_info.output_sub_size, vertical->is_gather, STBIR__V_FIRST_INFO_POINTER ); + + // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect) + decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + +#if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) + if ( effective_channels == 3 ) + decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations) +#endif + + ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + + // if we do vertical first, the ring buffer holds a whole decoded line + if ( vertical_first ) + ring_buffer_length_bytes = ( decode_buffer_size + 15 ) & ~15; + + if ( ( ring_buffer_length_bytes & 4095 ) == 0 ) ring_buffer_length_bytes += 64*3; // avoid 4k alias + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + alloc_ring_buffer_num_entries = vertical->filter_pixel_width + 1; + + // we never need more ring buffer entries than the scanlines we're outputting when in scatter mode + if ( ( !vertical->is_gather ) && ( alloc_ring_buffer_num_entries > conservative_split_output_size ) ) + alloc_ring_buffer_num_entries = conservative_split_output_size; + + ring_buffer_size = alloc_ring_buffer_num_entries * ring_buffer_length_bytes; + + // The vertical buffer is used differently, depending on whether we are scattering + // the vertical scanlines, or gathering them. + // If scattering, it's used at the temp buffer to accumulate each output. + // If gathering, it's just the output buffer. + vertical_buffer_size = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + + // we make two passes through this loop, 1st to add everything up, 2nd to allocate and init + for(;;) + { + int i; + void * advance_mem = alloced; + int copy_horizontal = 0; + stbir__sampler * possibly_use_horizontal_for_pivot = 0; + +#ifdef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__NEXT_PTR( ptr, size, ntype ) if ( alloced ) { void * p = STBIR_MALLOC( size, user_data); if ( p == 0 ) { stbir__free_internal_mem( info ); return 0; } (ptr) = (ntype*)p; } +#else + #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size); +#endif + + STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info ); + + STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info ); + + if ( info ) + { + static stbir__alpha_weight_func * fancy_alpha_weights[6] = { stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_2ch, stbir__fancy_alpha_weight_2ch }; + static stbir__alpha_unweight_func * fancy_alpha_unweights[6] = { stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_2ch, stbir__fancy_alpha_unweight_2ch }; + static stbir__alpha_weight_func * simple_alpha_weights[6] = { stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_2ch, stbir__simple_alpha_weight_2ch }; + static stbir__alpha_unweight_func * simple_alpha_unweights[6] = { stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_2ch, stbir__simple_alpha_unweight_2ch }; + + // initialize info fields + info->alloced_mem = alloced; + info->alloced_total = alloced_total; + + info->channels = channels; + info->effective_channels = effective_channels; + + info->offset_x = new_x; + info->offset_y = new_y; + info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries; + info->ring_buffer_num_entries = 0; + info->ring_buffer_length_bytes = ring_buffer_length_bytes; + info->splits = splits; + info->vertical_first = vertical_first; + + info->input_pixel_layout_internal = input_pixel_layout; + info->output_pixel_layout_internal = output_pixel_layout; + + // setup alpha weight functions + info->alpha_weight = 0; + info->alpha_unweight = 0; + + // handle alpha weighting functions and overrides + if ( alpha_weighting_type == 2 ) + { + // high quality alpha multiplying on the way in, dividing on the way out + info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_unweight = fancy_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 4 ) + { + // fast alpha multiplying on the way in, dividing on the way out + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 1 ) + { + // fast alpha on the way in, leave in premultiplied form on way out + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 3 ) + { + // incoming is premultiplied, fast alpha dividing on the way out - non-premultiplied output + info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + + // handle 3-chan color flipping, using the alpha weight path + if ( ( ( input_pixel_layout == STBIRI_RGB ) && ( output_pixel_layout == STBIRI_BGR ) ) || + ( ( input_pixel_layout == STBIRI_BGR ) && ( output_pixel_layout == STBIRI_RGB ) ) ) + { + // do the flipping on the smaller of the two ends + if ( horizontal->scale_info.scale < 1.0f ) + info->alpha_unweight = stbir__simple_flip_3ch; + else + info->alpha_weight = stbir__simple_flip_3ch; + } + + } + + // get all the per-split buffers + for( i = 0 ; i < splits ; i++ ) + { + STBIR__NEXT_PTR( info->split_info[i].decode_buffer, decode_buffer_size, float ); + +#ifdef STBIR__SEPARATE_ALLOCATIONS + + #ifdef STBIR_SIMD8 + if ( ( info ) && ( effective_channels == 3 ) ) + ++info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer + #endif + + STBIR__NEXT_PTR( info->split_info[i].ring_buffers, alloc_ring_buffer_num_entries * sizeof(float*), float* ); + { + int j; + for( j = 0 ; j < alloc_ring_buffer_num_entries ; j++ ) + { + STBIR__NEXT_PTR( info->split_info[i].ring_buffers[j], ring_buffer_length_bytes, float ); + #ifdef STBIR_SIMD8 + if ( ( info ) && ( effective_channels == 3 ) ) + ++info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer + #endif + } + } +#else + STBIR__NEXT_PTR( info->split_info[i].ring_buffer, ring_buffer_size, float ); +#endif + STBIR__NEXT_PTR( info->split_info[i].vertical_buffer, vertical_buffer_size, float ); + } + + // alloc memory for to-be-pivoted coeffs (if necessary) + if ( vertical->is_gather == 0 ) + { + int both; + int temp_mem_amt; + + // when in vertical scatter mode, we first build the coefficients in gather mode, and then pivot after, + // that means we need two buffers, so we try to use the decode buffer and ring buffer for this. if that + // is too small, we just allocate extra memory to use as this temp. + + both = vertical->gather_prescatter_contributors_size + vertical->gather_prescatter_coefficients_size; + +#ifdef STBIR__SEPARATE_ALLOCATIONS + temp_mem_amt = decode_buffer_size; + + #ifdef STBIR_SIMD8 + if ( effective_channels == 3 ) + --temp_mem_amt; // avx in 3 channel mode needs one float at the start of the buffer + #endif +#else + temp_mem_amt = ( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * splits; +#endif + if ( temp_mem_amt >= both ) + { + if ( info ) + { + vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer; + vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size ); + } + } + else + { + // ring+decode memory is too small, so allocate temp memory + STBIR__NEXT_PTR( vertical->gather_prescatter_contributors, vertical->gather_prescatter_contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( vertical->gather_prescatter_coefficients, vertical->gather_prescatter_coefficients_size, float ); + } + } + + STBIR__NEXT_PTR( horizontal->contributors, horizontal->contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( horizontal->coefficients, horizontal->coefficients_size, float ); + + // are the two filters identical?? (happens a lot with mipmap generation) + if ( ( horizontal->filter_kernel == vertical->filter_kernel ) && ( horizontal->filter_support == vertical->filter_support ) && ( horizontal->edge == vertical->edge ) && ( horizontal->scale_info.output_sub_size == vertical->scale_info.output_sub_size ) ) + { + float diff_scale = horizontal->scale_info.scale - vertical->scale_info.scale; + float diff_shift = horizontal->scale_info.pixel_shift - vertical->scale_info.pixel_shift; + if ( diff_scale < 0.0f ) diff_scale = -diff_scale; + if ( diff_shift < 0.0f ) diff_shift = -diff_shift; + if ( ( diff_scale <= stbir__small_float ) && ( diff_shift <= stbir__small_float ) ) + { + if ( horizontal->is_gather == vertical->is_gather ) + { + copy_horizontal = 1; + goto no_vert_alloc; + } + // everything matches, but vertical is scatter, horizontal is gather, use horizontal coeffs for vertical pivot coeffs + possibly_use_horizontal_for_pivot = horizontal; + } + } + + STBIR__NEXT_PTR( vertical->contributors, vertical->contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( vertical->coefficients, vertical->coefficients_size, float ); + + no_vert_alloc: + + if ( info ) + { + STBIR_PROFILE_BUILD_START( horizontal ); + + stbir__calculate_filters( horizontal, 0, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + + // setup the horizontal gather functions + // start with defaulting to the n_coeffs functions (specialized on channels and remnant leftover) + info->horizontal_gather_channels = stbir__horizontal_gather_n_coeffs_funcs[ effective_channels ][ horizontal->extent_info.widest & 3 ]; + // but if the number of coeffs <= 12, use another set of special cases. <=12 coeffs is any enlarging resize, or shrinking resize down to about 1/3 size + if ( horizontal->extent_info.widest <= 12 ) + info->horizontal_gather_channels = stbir__horizontal_gather_channels_funcs[ effective_channels ][ horizontal->extent_info.widest - 1 ]; + + info->scanline_extents.conservative.n0 = conservative->n0; + info->scanline_extents.conservative.n1 = conservative->n1; + + // get exact extents + stbir__get_extents( horizontal, &info->scanline_extents ); + + // pack the horizontal coeffs + horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n0, info->scanline_extents.conservative.n1 ); + + STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) ); + + STBIR_PROFILE_BUILD_END( horizontal ); + + if ( copy_horizontal ) + { + STBIR_MEMCPY( &info->vertical, horizontal, sizeof( stbir__sampler ) ); + } + else + { + STBIR_PROFILE_BUILD_START( vertical ); + + stbir__calculate_filters( vertical, possibly_use_horizontal_for_pivot, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + STBIR_MEMCPY( &info->vertical, vertical, sizeof( stbir__sampler ) ); + + STBIR_PROFILE_BUILD_END( vertical ); + } + + // setup the vertical split ranges + stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size ); + + // now we know precisely how many entries we need + info->ring_buffer_num_entries = info->vertical.extent_info.widest; + + // we never need more ring buffer entries than the scanlines we're outputting + if ( ( !info->vertical.is_gather ) && ( info->ring_buffer_num_entries > conservative_split_output_size ) ) + info->ring_buffer_num_entries = conservative_split_output_size; + STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries ); + + // a few of the horizontal gather functions read past the end of the decode (but mask it out), + // so put in normal values so no snans or denormals accidentally sneak in (also, in the ring + // buffer for vertical first) + for( i = 0 ; i < splits ; i++ ) + { + int t, ofs, start; + + ofs = decode_buffer_size / 4; + + #if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) + if ( effective_channels == 3 ) + --ofs; // avx in 3 channel mode needs one float at the start of the buffer, so we snap back for clearing + #endif + + start = ofs - 4; + if ( start < 0 ) start = 0; + + for( t = start ; t < ofs; t++ ) + info->split_info[i].decode_buffer[ t ] = 9999.0f; + + if ( vertical_first ) + { + int j; + for( j = 0; j < info->ring_buffer_num_entries ; j++ ) + { + for( t = start ; t < ofs; t++ ) + stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ t ] = 9999.0f; + } + } + } + } + + #undef STBIR__NEXT_PTR + + + // is this the first time through loop? + if ( info == 0 ) + { + alloced_total = ( 15 + (size_t)advance_mem ); + alloced = STBIR_MALLOC( alloced_total, user_data ); + if ( alloced == 0 ) + return 0; + } + else + return info; // success + } +} + +static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count ) +{ + stbir__per_split_info * split_info = info->split_info + split_start; + + STBIR_PROFILE_CLEAR_EXTRAS(); + + STBIR_PROFILE_FIRST_START( looping ); + if (info->vertical.is_gather) + stbir__vertical_gather_loop( info, split_info, split_count ); + else + stbir__vertical_scatter_loop( info, split_info, split_count ); + STBIR_PROFILE_END( looping ); + + return 1; +} + +static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * resize ) +{ + static stbir__decode_pixels_func * decode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear, + }; + + static stbir__decode_pixels_func * decode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + { /* RGBA */ stbir__decode_uint8_srgb4_linearalpha, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear }, + { /* BGRA */ stbir__decode_uint8_srgb4_linearalpha_BGRA, stbir__decode_uint8_srgb_BGRA, 0, stbir__decode_float_linear_BGRA, stbir__decode_half_float_linear_BGRA }, + { /* ARGB */ stbir__decode_uint8_srgb4_linearalpha_ARGB, stbir__decode_uint8_srgb_ARGB, 0, stbir__decode_float_linear_ARGB, stbir__decode_half_float_linear_ARGB }, + { /* ABGR */ stbir__decode_uint8_srgb4_linearalpha_ABGR, stbir__decode_uint8_srgb_ABGR, 0, stbir__decode_float_linear_ABGR, stbir__decode_half_float_linear_ABGR }, + { /* RA */ stbir__decode_uint8_srgb2_linearalpha, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear }, + { /* AR */ stbir__decode_uint8_srgb2_linearalpha_AR, stbir__decode_uint8_srgb_AR, 0, stbir__decode_float_linear_AR, stbir__decode_half_float_linear_AR }, + }; + + static stbir__decode_pixels_func * decode_simple_scaled_or_not[2][2]= + { + { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear }, + }; + + static stbir__decode_pixels_func * decode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]= + { + { /* RGBA */ { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear } }, + { /* BGRA */ { stbir__decode_uint8_linear_scaled_BGRA, stbir__decode_uint8_linear_BGRA }, { stbir__decode_uint16_linear_scaled_BGRA, stbir__decode_uint16_linear_BGRA } }, + { /* ARGB */ { stbir__decode_uint8_linear_scaled_ARGB, stbir__decode_uint8_linear_ARGB }, { stbir__decode_uint16_linear_scaled_ARGB, stbir__decode_uint16_linear_ARGB } }, + { /* ABGR */ { stbir__decode_uint8_linear_scaled_ABGR, stbir__decode_uint8_linear_ABGR }, { stbir__decode_uint16_linear_scaled_ABGR, stbir__decode_uint16_linear_ABGR } }, + { /* RA */ { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear } }, + { /* AR */ { stbir__decode_uint8_linear_scaled_AR, stbir__decode_uint8_linear_AR }, { stbir__decode_uint16_linear_scaled_AR, stbir__decode_uint16_linear_AR } } + }; + + static stbir__encode_pixels_func * encode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + /* 1ch-4ch */ stbir__encode_uint8_srgb, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear, + }; + + static stbir__encode_pixels_func * encode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + { /* RGBA */ stbir__encode_uint8_srgb4_linearalpha, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear }, + { /* BGRA */ stbir__encode_uint8_srgb4_linearalpha_BGRA, stbir__encode_uint8_srgb_BGRA, 0, stbir__encode_float_linear_BGRA, stbir__encode_half_float_linear_BGRA }, + { /* ARGB */ stbir__encode_uint8_srgb4_linearalpha_ARGB, stbir__encode_uint8_srgb_ARGB, 0, stbir__encode_float_linear_ARGB, stbir__encode_half_float_linear_ARGB }, + { /* ABGR */ stbir__encode_uint8_srgb4_linearalpha_ABGR, stbir__encode_uint8_srgb_ABGR, 0, stbir__encode_float_linear_ABGR, stbir__encode_half_float_linear_ABGR }, + { /* RA */ stbir__encode_uint8_srgb2_linearalpha, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear }, + { /* AR */ stbir__encode_uint8_srgb2_linearalpha_AR, stbir__encode_uint8_srgb_AR, 0, stbir__encode_float_linear_AR, stbir__encode_half_float_linear_AR } + }; + + static stbir__encode_pixels_func * encode_simple_scaled_or_not[2][2]= + { + { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear }, + }; + + static stbir__encode_pixels_func * encode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]= + { + { /* RGBA */ { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear } }, + { /* BGRA */ { stbir__encode_uint8_linear_scaled_BGRA, stbir__encode_uint8_linear_BGRA }, { stbir__encode_uint16_linear_scaled_BGRA, stbir__encode_uint16_linear_BGRA } }, + { /* ARGB */ { stbir__encode_uint8_linear_scaled_ARGB, stbir__encode_uint8_linear_ARGB }, { stbir__encode_uint16_linear_scaled_ARGB, stbir__encode_uint16_linear_ARGB } }, + { /* ABGR */ { stbir__encode_uint8_linear_scaled_ABGR, stbir__encode_uint8_linear_ABGR }, { stbir__encode_uint16_linear_scaled_ABGR, stbir__encode_uint16_linear_ABGR } }, + { /* RA */ { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear } }, + { /* AR */ { stbir__encode_uint8_linear_scaled_AR, stbir__encode_uint8_linear_AR }, { stbir__encode_uint16_linear_scaled_AR, stbir__encode_uint16_linear_AR } } + }; + + stbir__decode_pixels_func * decode_pixels = 0; + stbir__encode_pixels_func * encode_pixels = 0; + stbir_datatype input_type, output_type; + + input_type = resize->input_data_type; + output_type = resize->output_data_type; + info->input_data = resize->input_pixels; + info->input_stride_bytes = resize->input_stride_in_bytes; + info->output_stride_bytes = resize->output_stride_in_bytes; + + // if we're completely point sampling, then we can turn off SRGB + if ( ( info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( info->vertical.filter_enum == STBIR_FILTER_POINT_SAMPLE ) ) + { + if ( ( ( input_type == STBIR_TYPE_UINT8_SRGB ) || ( input_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) && + ( ( output_type == STBIR_TYPE_UINT8_SRGB ) || ( output_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) ) + { + input_type = STBIR_TYPE_UINT8; + output_type = STBIR_TYPE_UINT8; + } + } + + // recalc the output and input strides + if ( info->input_stride_bytes == 0 ) + info->input_stride_bytes = info->channels * info->horizontal.scale_info.input_full_size * stbir__type_size[input_type]; + + if ( info->output_stride_bytes == 0 ) + info->output_stride_bytes = info->channels * info->horizontal.scale_info.output_sub_size * stbir__type_size[output_type]; + + // calc offset + info->output_data = ( (char*) resize->output_pixels ) + ( (size_t) info->offset_y * (size_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] ); + + info->in_pixels_cb = resize->input_cb; + info->user_data = resize->user_data; + info->out_pixels_cb = resize->output_cb; + + // setup the input format converters + if ( ( input_type == STBIR_TYPE_UINT8 ) || ( input_type == STBIR_TYPE_UINT16 ) ) + { + int non_scaled = 0; + + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) + if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) + if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) + non_scaled = 1; + + if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL ) + decode_pixels = decode_simple_scaled_or_not[ input_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + else + decode_pixels = decode_alphas_scaled_or_not[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + } + else + { + if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL ) + decode_pixels = decode_simple[ input_type - STBIR_TYPE_UINT8_SRGB ]; + else + decode_pixels = decode_alphas[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type - STBIR_TYPE_UINT8_SRGB ]; + } + + // setup the output format converters + if ( ( output_type == STBIR_TYPE_UINT8 ) || ( output_type == STBIR_TYPE_UINT16 ) ) + { + int non_scaled = 0; + + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) + if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) + if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) + non_scaled = 1; + + if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL ) + encode_pixels = encode_simple_scaled_or_not[ output_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + else + encode_pixels = encode_alphas_scaled_or_not[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + } + else + { + if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL ) + encode_pixels = encode_simple[ output_type - STBIR_TYPE_UINT8_SRGB ]; + else + encode_pixels = encode_alphas[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type - STBIR_TYPE_UINT8_SRGB ]; + } + + info->input_type = input_type; + info->output_type = output_type; + info->decode_pixels = decode_pixels; + info->encode_pixels = encode_pixels; +} + +static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, double * u1 ) +{ + double per, adj; + int over; + + // do left/top edge + if ( *outx < 0 ) + { + per = ( (double)*outx ) / ( (double)*outsubw ); // is negative + adj = per * ( *u1 - *u0 ); + *u0 -= adj; // increases u0 + *outx = 0; + } + + // do right/bot edge + over = outw - ( *outx + *outsubw ); + if ( over < 0 ) + { + per = ( (double)over ) / ( (double)*outsubw ); // is negative + adj = per * ( *u1 - *u0 ); + *u1 += adj; // decrease u1 + *outsubw = outw - *outx; + } +} + +// converts a double to a rational that has less than one float bit of error (returns 0 if unable to do so) +static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 *numer, stbir_uint32 *denom, int limit_denom ) // limit_denom (1) or limit numer (0) +{ + double err; + stbir_uint64 top, bot; + stbir_uint64 numer_last = 0; + stbir_uint64 denom_last = 1; + stbir_uint64 numer_estimate = 1; + stbir_uint64 denom_estimate = 0; + + // scale to past float error range + top = (stbir_uint64)( f * (double)(1 << 25) ); + bot = 1 << 25; + + // keep refining, but usually stops in a few loops - usually 5 for bad cases + for(;;) + { + stbir_uint64 est, temp; + + // hit limit, break out and do best full range estimate + if ( ( ( limit_denom ) ? denom_estimate : numer_estimate ) >= limit ) + break; + + // is the current error less than 1 bit of a float? if so, we're done + if ( denom_estimate ) + { + err = ( (double)numer_estimate / (double)denom_estimate ) - f; + if ( err < 0.0 ) err = -err; + if ( err < ( 1.0 / (double)(1<<24) ) ) + { + // yup, found it + *numer = (stbir_uint32) numer_estimate; + *denom = (stbir_uint32) denom_estimate; + return 1; + } + } + + // no more refinement bits left? break out and do full range estimate + if ( bot == 0 ) + break; + + // gcd the estimate bits + est = top / bot; + temp = top % bot; + top = bot; + bot = temp; + + // move remainders + temp = est * denom_estimate + denom_last; + denom_last = denom_estimate; + denom_estimate = temp; + + // move remainders + temp = est * numer_estimate + numer_last; + numer_last = numer_estimate; + numer_estimate = temp; + } + + // we didn't fine anything good enough for float, use a full range estimate + if ( limit_denom ) + { + numer_estimate= (stbir_uint64)( f * (double)limit + 0.5 ); + denom_estimate = limit; + } + else + { + numer_estimate = limit; + denom_estimate = (stbir_uint64)( ( (double)limit / f ) + 0.5 ); + } + + *numer = (stbir_uint32) numer_estimate; + *denom = (stbir_uint32) denom_estimate; + + err = ( denom_estimate ) ? ( ( (double)(stbir_uint32)numer_estimate / (double)(stbir_uint32)denom_estimate ) - f ) : 1.0; + if ( err < 0.0 ) err = -err; + return ( err < ( 1.0 / (double)(1<<24) ) ) ? 1 : 0; +} + +static int stbir__calculate_region_transform( stbir__scale_info * scale_info, int output_full_range, int * output_offset, int output_sub_range, int input_full_range, double input_s0, double input_s1 ) +{ + double output_range, input_range, output_s, input_s, ratio, scale; + + input_s = input_s1 - input_s0; + + // null area + if ( ( output_full_range == 0 ) || ( input_full_range == 0 ) || + ( output_sub_range == 0 ) || ( input_s <= stbir__small_float ) ) + return 0; + + // are either of the ranges completely out of bounds? + if ( ( *output_offset >= output_full_range ) || ( ( *output_offset + output_sub_range ) <= 0 ) || ( input_s0 >= (1.0f-stbir__small_float) ) || ( input_s1 <= stbir__small_float ) ) + return 0; + + output_range = (double)output_full_range; + input_range = (double)input_full_range; + + output_s = ( (double)output_sub_range) / output_range; + + // figure out the scaling to use + ratio = output_s / input_s; + + // save scale before clipping + scale = ( output_range / input_range ) * ratio; + scale_info->scale = (float)scale; + scale_info->inv_scale = (float)( 1.0 / scale ); + + // clip output area to left/right output edges (and adjust input area) + stbir__clip( output_offset, &output_sub_range, output_full_range, &input_s0, &input_s1 ); + + // recalc input area + input_s = input_s1 - input_s0; + + // after clipping do we have zero input area? + if ( input_s <= stbir__small_float ) + return 0; + + // calculate and store the starting source offsets in output pixel space + scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range ); + + scale_info->scale_is_rational = stbir__double_to_rational( scale, ( scale <= 1.0 ) ? output_full_range : input_full_range, &scale_info->scale_numerator, &scale_info->scale_denominator, ( scale >= 1.0 ) ); + + scale_info->input_full_size = input_full_range; + scale_info->output_sub_size = output_sub_range; + + return 1; +} + + +static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layout pixel_layout, stbir_datatype data_type ) +{ + resize->input_cb = 0; + resize->output_cb = 0; + resize->user_data = resize; + resize->samplers = 0; + resize->called_alloc = 0; + resize->horizontal_filter = STBIR_FILTER_DEFAULT; + resize->horizontal_filter_kernel = 0; resize->horizontal_filter_support = 0; + resize->vertical_filter = STBIR_FILTER_DEFAULT; + resize->vertical_filter_kernel = 0; resize->vertical_filter_support = 0; + resize->horizontal_edge = STBIR_EDGE_CLAMP; + resize->vertical_edge = STBIR_EDGE_CLAMP; + resize->input_s0 = 0; resize->input_t0 = 0; resize->input_s1 = 1; resize->input_t1 = 1; + resize->output_subx = 0; resize->output_suby = 0; resize->output_subw = resize->output_w; resize->output_subh = resize->output_h; + resize->input_data_type = data_type; + resize->output_data_type = data_type; + resize->input_pixel_layout_public = pixel_layout; + resize->output_pixel_layout_public = pixel_layout; + resize->needs_rebuild = 1; +} + +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, + const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero + stbir_pixel_layout pixel_layout, stbir_datatype data_type ) +{ + resize->input_pixels = input_pixels; + resize->input_w = input_w; + resize->input_h = input_h; + resize->input_stride_in_bytes = input_stride_in_bytes; + resize->output_pixels = output_pixels; + resize->output_w = output_w; + resize->output_h = output_h; + resize->output_stride_in_bytes = output_stride_in_bytes; + resize->fast_alpha = 0; + + stbir__init_and_set_layout( resize, pixel_layout, data_type ); +} + +// You can update parameters any time after resize_init +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ) // by default, datatype from resize_init +{ + resize->input_data_type = input_type; + resize->output_data_type = output_type; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); +} + +STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ) // no callbacks by default +{ + resize->input_cb = input_cb; + resize->output_cb = output_cb; + + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + { + resize->samplers->in_pixels_cb = input_cb; + resize->samplers->out_pixels_cb = output_cb; + } +} + +STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ) // pass back STBIR_RESIZE* by default +{ + resize->user_data = user_data; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + resize->samplers->user_data = user_data; +} + +STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ) +{ + resize->input_pixels = input_pixels; + resize->input_stride_in_bytes = input_stride_in_bytes; + resize->output_pixels = output_pixels; + resize->output_stride_in_bytes = output_stride_in_bytes; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); +} + + +STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ) // CLAMP by default +{ + resize->horizontal_edge = horizontal_edge; + resize->vertical_edge = vertical_edge; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ) // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default +{ + resize->horizontal_filter = horizontal_filter; + resize->vertical_filter = vertical_filter; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ) +{ + resize->horizontal_filter_kernel = horizontal_filter; resize->horizontal_filter_support = horizontal_support; + resize->vertical_filter_kernel = vertical_filter; resize->vertical_filter_support = vertical_support; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout ) // sets new pixel layouts +{ + resize->input_pixel_layout_public = input_pixel_layout; + resize->output_pixel_layout_public = output_pixel_layout; + resize->needs_rebuild = 1; + return 1; +} + + +STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality ) // sets alpha speed +{ + resize->fast_alpha = non_pma_alpha_speed_over_quality; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ) // sets input region (full region by default) +{ + resize->input_s0 = s0; + resize->input_t0 = t0; + resize->input_s1 = s1; + resize->input_t1 = t1; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( s1 < stbir__small_float ) || ( (s1-s0) < stbir__small_float ) || + ( t1 < stbir__small_float ) || ( (t1-t0) < stbir__small_float ) || + ( s0 > (1.0f-stbir__small_float) ) || + ( t0 > (1.0f-stbir__small_float) ) ) + return 0; + + return 1; +} + +STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ) // sets input region (full region by default) +{ + resize->output_subx = subx; + resize->output_suby = suby; + resize->output_subw = subw; + resize->output_subh = subh; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) ) + return 0; + + return 1; +} + +STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ) // sets both regions (full regions by default) +{ + double s0, t0, s1, t1; + + s0 = ( (double)subx ) / ( (double)resize->output_w ); + t0 = ( (double)suby ) / ( (double)resize->output_h ); + s1 = ( (double)(subx+subw) ) / ( (double)resize->output_w ); + t1 = ( (double)(suby+subh) ) / ( (double)resize->output_h ); + + resize->input_s0 = s0; + resize->input_t0 = t0; + resize->input_s1 = s1; + resize->input_t1 = t1; + resize->output_subx = subx; + resize->output_suby = suby; + resize->output_subw = subw; + resize->output_subh = subh; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) ) + return 0; + + return 1; +} + +static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) +{ + stbir__contributors conservative = { 0, 0 }; + stbir__sampler horizontal, vertical; + int new_output_subx, new_output_suby; + stbir__info * out_info; + #ifdef STBIR_PROFILE + stbir__info profile_infod; // used to contain building profile info before everything is allocated + stbir__info * profile_info = &profile_infod; + #endif + + // have we already built the samplers? + if ( resize->samplers ) + return 0; + + #define STBIR_RETURN_ERROR_AND_ASSERT( exp ) STBIR_ASSERT( !(exp) ); if (exp) return 0; + STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->horizontal_filter >= STBIR_FILTER_OTHER) + STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->vertical_filter >= STBIR_FILTER_OTHER) + #undef STBIR_RETURN_ERROR_AND_ASSERT + + if ( splits <= 0 ) + return 0; + + STBIR_PROFILE_BUILD_FIRST_START( build ); + + new_output_subx = resize->output_subx; + new_output_suby = resize->output_suby; + + // do horizontal clip and scale calcs + if ( !stbir__calculate_region_transform( &horizontal.scale_info, resize->output_w, &new_output_subx, resize->output_subw, resize->input_w, resize->input_s0, resize->input_s1 ) ) + return 0; + + // do vertical clip and scale calcs + if ( !stbir__calculate_region_transform( &vertical.scale_info, resize->output_h, &new_output_suby, resize->output_subh, resize->input_h, resize->input_t0, resize->input_t1 ) ) + return 0; + + // if nothing to do, just return + if ( ( horizontal.scale_info.output_sub_size == 0 ) || ( vertical.scale_info.output_sub_size == 0 ) ) + return 0; + + stbir__set_sampler(&horizontal, resize->horizontal_filter, resize->horizontal_filter_kernel, resize->horizontal_filter_support, resize->horizontal_edge, &horizontal.scale_info, 1, resize->user_data ); + stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data ); + stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data ); + + if ( ( vertical.scale_info.output_sub_size / splits ) < STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS ) // each split should be a minimum of 4 scanlines (handwavey choice) + { + splits = vertical.scale_info.output_sub_size / STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS; + if ( splits == 0 ) splits = 1; + } + + STBIR_PROFILE_BUILD_START( alloc ); + out_info = stbir__alloc_internal_mem_and_build_samplers( &horizontal, &vertical, &conservative, resize->input_pixel_layout_public, resize->output_pixel_layout_public, splits, new_output_subx, new_output_suby, resize->fast_alpha, resize->user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + STBIR_PROFILE_BUILD_END( alloc ); + STBIR_PROFILE_BUILD_END( build ); + + if ( out_info ) + { + resize->splits = splits; + resize->samplers = out_info; + resize->needs_rebuild = 0; + #ifdef STBIR_PROFILE + STBIR_MEMCPY( &out_info->profile, &profile_infod.profile, sizeof( out_info->profile ) ); + #endif + + // update anything that can be changed without recalcing samplers + stbir__update_info_from_resize( out_info, resize ); + + return splits; + } + + return 0; +} + +void stbir_free_samplers( STBIR_RESIZE * resize ) +{ + if ( resize->samplers ) + { + stbir__free_internal_mem( resize->samplers ); + resize->samplers = 0; + resize->called_alloc = 0; + } +} + +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int splits ) +{ + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + { + if ( resize->samplers ) + stbir_free_samplers( resize ); + + resize->called_alloc = 1; + return stbir__perform_build( resize, splits ); + } + + STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); + + return 1; +} + +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ) +{ + return stbir_build_samplers_with_splits( resize, 1 ); +} + +STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) +{ + int result; + + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + { + int alloc_state = resize->called_alloc; // remember allocated state + + if ( resize->samplers ) + { + stbir__free_internal_mem( resize->samplers ); + resize->samplers = 0; + } + + if ( !stbir_build_samplers( resize ) ) + return 0; + + resize->called_alloc = alloc_state; + + // if build_samplers succeeded (above), but there are no samplers set, then + // the area to stretch into was zero pixels, so don't do anything and return + // success + if ( resize->samplers == 0 ) + return 1; + } + else + { + // didn't build anything - clear it + STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); + } + + // do resize + result = stbir__perform_resize( resize->samplers, 0, resize->splits ); + + // if we alloced, then free + if ( !resize->called_alloc ) + { + stbir_free_samplers( resize ); + resize->samplers = 0; + } + + return result; +} + +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ) +{ + STBIR_ASSERT( resize->samplers ); + + // if we're just doing the whole thing, call full + if ( ( split_start == -1 ) || ( ( split_start == 0 ) && ( split_count == resize->splits ) ) ) + return stbir_resize_extended( resize ); + + // you **must** build samplers first when using split resize + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + return 0; + + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) + return 0; + + // do resize + return stbir__perform_resize( resize->samplers, split_start, split_count ); +} + +static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * output_pixels, int type_size, int output_w, int output_h, int output_stride_in_bytes, stbir_internal_pixel_layout pixel_layout ) +{ + size_t size; + int pitch; + void * ptr; + + pitch = output_w * type_size * stbir__pixel_channels[ pixel_layout ]; + if ( pitch == 0 ) + return 0; + + if ( output_stride_in_bytes == 0 ) + output_stride_in_bytes = pitch; + + if ( output_stride_in_bytes < pitch ) + return 0; + + size = (size_t)output_stride_in_bytes * (size_t)output_h; + if ( size == 0 ) + return 0; + + *ret_ptr = 0; + *ret_pitch = output_stride_in_bytes; + + if ( output_pixels == 0 ) + { + ptr = STBIR_MALLOC( size, 0 ); + if ( ptr == 0 ) + return 0; + + *ret_ptr = ptr; + *ret_pitch = pitch; + } + + return 1; +} + + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + unsigned char * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_UINT8 ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + unsigned char * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_UINT8_SRGB ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + float * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_FLOAT ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + + +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ) +{ + STBIR_RESIZE resize; + float * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, data_type ); + + resize.horizontal_edge = edge; + resize.vertical_edge = edge; + resize.horizontal_filter = filter; + resize.vertical_filter = filter; + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + +#ifdef STBIR_PROFILE + +STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) +{ + static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient piovot" } ; + stbir__info* samp = resize->samplers; + int i; + + typedef int testa[ (STBIR__ARRAY_SIZE( bdescriptions ) == (STBIR__ARRAY_SIZE( samp->profile.array )-1) )?1:-1]; + typedef int testb[ (sizeof( samp->profile.array ) == (sizeof(samp->profile.named)) )?1:-1]; + typedef int testc[ (sizeof( info->clocks ) >= (sizeof(samp->profile.named)) )?1:-1]; + + for( i = 0 ; i < STBIR__ARRAY_SIZE( bdescriptions ) ; i++) + info->clocks[i] = samp->profile.array[i+1]; + + info->total_clocks = samp->profile.named.total; + info->descriptions = bdescriptions; + info->count = STBIR__ARRAY_SIZE( bdescriptions ); +} + +STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize, int split_start, int split_count ) +{ + static char const * descriptions[7] = { "Looping", "Vertical sampling", "Horizontal sampling", "Scanline input", "Scanline output", "Alpha weighting", "Alpha unweighting" }; + stbir__per_split_info * split_info; + int s, i; + + typedef int testa[ (STBIR__ARRAY_SIZE( descriptions ) == (STBIR__ARRAY_SIZE( split_info->profile.array )-1) )?1:-1]; + typedef int testb[ (sizeof( split_info->profile.array ) == (sizeof(split_info->profile.named)) )?1:-1]; + typedef int testc[ (sizeof( info->clocks ) >= (sizeof(split_info->profile.named)) )?1:-1]; + + if ( split_start == -1 ) + { + split_start = 0; + split_count = resize->samplers->splits; + } + + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) + { + info->total_clocks = 0; + info->descriptions = 0; + info->count = 0; + return; + } + + split_info = resize->samplers->split_info + split_start; + + // sum up the profile from all the splits + for( i = 0 ; i < STBIR__ARRAY_SIZE( descriptions ) ; i++ ) + { + stbir_uint64 sum = 0; + for( s = 0 ; s < split_count ; s++ ) + sum += split_info[s].profile.array[i+1]; + info->clocks[i] = sum; + } + + info->total_clocks = split_info->profile.named.total; + info->descriptions = descriptions; + info->count = STBIR__ARRAY_SIZE( descriptions ); +} + +STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) +{ + stbir_resize_split_profile_info( info, resize, -1, 0 ); +} + +#endif // STBIR_PROFILE + +#undef STBIR_BGR +#undef STBIR_1CHANNEL +#undef STBIR_2CHANNEL +#undef STBIR_RGB +#undef STBIR_RGBA +#undef STBIR_4CHANNEL +#undef STBIR_BGRA +#undef STBIR_ARGB +#undef STBIR_ABGR +#undef STBIR_RA +#undef STBIR_AR +#undef STBIR_RGBA_PM +#undef STBIR_BGRA_PM +#undef STBIR_ARGB_PM +#undef STBIR_ABGR_PM +#undef STBIR_RA_PM +#undef STBIR_AR_PM + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +#else // STB_IMAGE_RESIZE_HORIZONTALS&STB_IMAGE_RESIZE_DO_VERTICALS + +// we reinclude the header file to define all the horizontal functions +// specializing each function for the number of coeffs is 20-40% faster *OVERALL* + +// by including the header file again this way, we can still debug the functions + +#define STBIR_strs_join2( start, mid, end ) start##mid##end +#define STBIR_strs_join1( start, mid, end ) STBIR_strs_join2( start, mid, end ) + +#define STBIR_strs_join24( start, mid1, mid2, end ) start##mid1##mid2##end +#define STBIR_strs_join14( start, mid1, mid2, end ) STBIR_strs_join24( start, mid1, mid2, end ) + +#ifdef STB_IMAGE_RESIZE_DO_CODERS + +#ifdef stbir__decode_suffix +#define STBIR__CODER_NAME( name ) STBIR_strs_join1( name, _, stbir__decode_suffix ) +#else +#define STBIR__CODER_NAME( name ) name +#endif + +#ifdef stbir__decode_swizzle +#define stbir__decode_simdf8_flip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3),stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg) +#define stbir__decode_simdf4_flip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg) +#define stbir__encode_simdf8_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3),stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg) +#define stbir__encode_simdf4_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg) +#else +#define stbir__decode_order0 0 +#define stbir__decode_order1 1 +#define stbir__decode_order2 2 +#define stbir__decode_order3 3 +#define stbir__encode_order0 0 +#define stbir__encode_order1 1 +#define stbir__encode_order2 2 +#define stbir__encode_order3 3 +#define stbir__decode_simdf8_flip(reg) +#define stbir__decode_simdf4_flip(reg) +#define stbir__encode_simdf8_unflip(reg) +#define stbir__encode_simdf4_unflip(reg) +#endif + +#ifdef STBIR_SIMD8 +#define stbir__encode_simdfX_unflip stbir__encode_simdf8_unflip +#else +#define stbir__encode_simdfX_unflip stbir__encode_simdf4_unflip +#endif + +static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const*)inputp; + + #ifdef STBIR_SIMD + unsigned char const * end_input_m16 = input + width_times_channels - 16; + if ( width_times_channels >= 16 ) + { + decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o0,o1; + stbir__simdf8 of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u8_to_u32( o0, o1, i ); + stbir__simdi8_convert_i32_to_float( of0, o0 ); + stbir__simdi8_convert_i32_to_float( of1, o1 ); + stbir__simdf8_mult( of0, of0, STBIR_max_uint8_as_float_inverted8); + stbir__simdf8_mult( of1, of1, STBIR_max_uint8_as_float_inverted8); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode + 0, of0 ); + stbir__simdf8_store( decode + 8, of1 ); + #else + stbir__simdi i, o0, o1, o2, o3; + stbir__simdf of0, of1, of2, of3; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdi_convert_i32_to_float( of2, o2 ); + stbir__simdi_convert_i32_to_float( of3, o3 ); + stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of2, of2, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of3, of3, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + stbir__simdf_store( decode + 8, of2 ); + stbir__simdf_store( decode + 12, of3 ); + #endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted; + decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted; + decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted; + decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint8_as_float_inverted; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted; + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp; + unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdi i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode ); + stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + #ifdef STBIR_SIMD8 + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdi_store( output, i ); + #else + stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdi_store2( output, i ); + #endif + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e0; + stbir__simdi i0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); + stbir__simdf_madd( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), e0 ); + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_pack_to_8bytes( i0, e0, e0 ); // only use first 4 + *(int*)(output-4) = stbir__simdi_to_int( i0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + stbir__simdf e0; + STBIR_NO_UNROLL(encode); + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_uint8( e0 ); + #if stbir__coder_min_num >= 2 + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_uint8( e0 ); + #endif + #if stbir__coder_min_num >= 3 + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_uint8( e0 ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f; + f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f; + f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f; + f = encode[stbir__encode_order3] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const*)inputp; + + #ifdef STBIR_SIMD + unsigned char const * end_input_m16 = input + width_times_channels - 16; + if ( width_times_channels >= 16 ) + { + decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o0,o1; + stbir__simdf8 of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u8_to_u32( o0, o1, i ); + stbir__simdi8_convert_i32_to_float( of0, o0 ); + stbir__simdi8_convert_i32_to_float( of1, o1 ); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode + 0, of0 ); + stbir__simdf8_store( decode + 8, of1 ); + #else + stbir__simdi i, o0, o1, o2, o3; + stbir__simdf of0, of1, of2, of3; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdi_convert_i32_to_float( of2, o2 ); + stbir__simdi_convert_i32_to_float( of3, o3 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + stbir__simdf_store( decode + 8, of2 ); + stbir__simdf_store( decode + 12, of3 ); +#endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])); + decode[1-4] = ((float)(input[stbir__decode_order1])); + decode[2-4] = ((float)(input[stbir__decode_order2])); + decode[3-4] = ((float)(input[stbir__decode_order3])); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])); + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp; + unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdi i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode ); + stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + #ifdef STBIR_SIMD8 + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdi_store( output, i ); + #else + stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdi_store2( output, i ); + #endif + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e0; + stbir__simdi i0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); + stbir__simdf_add( e0, STBIR__CONSTF(STBIR_simd_point5), e0 ); + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_pack_to_8bytes( i0, e0, e0 ); // only use first 4 + *(int*)(output-4) = stbir__simdi_to_int( i0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f; + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f; + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f; + f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ]; + decode[1-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ]; + decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ]; + decode[3-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order3 ] ]; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ]; + #if stbir__coder_min_num >= 2 + decode[1] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ]; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ]; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +#define stbir__min_max_shift20( i, f ) \ + stbir__simdf_max( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_zero )) ); \ + stbir__simdf_min( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_one )) ); \ + stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 ); + +#define stbir__scale_and_convert( i, f ) \ + stbir__simdf_madd( f, STBIR__CONSTF( STBIR_simd_point5 ), STBIR__CONSTF( STBIR_max_uint8_as_float ), f ); \ + stbir__simdf_max( f, f, stbir__simdf_zeroP() ); \ + stbir__simdf_min( f, f, STBIR__CONSTF( STBIR_max_uint8_as_float ) ); \ + stbir__simdf_convert_float_to_i32( i, f ); + +#define stbir__linear_to_srgb_finish( i, f ) \ +{ \ + stbir__simdi temp; \ + stbir__simdi_32shr( temp, stbir_simdi_castf( f ), 12 ) ; \ + stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mastissa_mask) ); \ + stbir__simdi_or( temp, temp, STBIR__CONSTI(STBIR_topscale) ); \ + stbir__simdi_16madd( i, i, temp ); \ + stbir__simdi_32shr( i, i, 16 ); \ +} + +#define stbir__simdi_table_lookup2( v0,v1, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ +} + +#define stbir__simdi_table_lookup3( v0,v1,v2, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1,temp2; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp2.m128i_i128 = v2; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ + v2 = temp2.m128i_i128; \ +} + +#define stbir__simdi_table_lookup4( v0,v1,v2,v3, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1,temp2,temp3; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp2.m128i_i128 = v2; \ + temp3.m128i_i128 = v3; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \ + temp3.m128i_u32[0] = table[temp3.m128i_i32[0]]; temp3.m128i_u32[1] = table[temp3.m128i_i32[1]]; temp3.m128i_u32[2] = table[temp3.m128i_i32[2]]; temp3.m128i_u32[3] = table[temp3.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ + v2 = temp2.m128i_i128; \ + v3 = temp3.m128i_i128; \ +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + STBIR_SIMD_NO_UNROLL(encode); + + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__min_max_shift20( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__min_max_shift20( i3, f3 ); + + stbir__simdi_table_lookup4( i0, i1, i2, i3, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i1, f1 ); + stbir__linear_to_srgb_finish( i2, f2 ); + stbir__linear_to_srgb_finish( i3, f3 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + encode += 16; + output += 16; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( output <= end_output ) + { + STBIR_SIMD_NO_UNROLL(encode); + + output[0-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); + output[1-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] ); + output[2-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] ); + output[3-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order3] ); + + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + STBIR_NO_UNROLL(encode); + output[0] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); + #if stbir__coder_min_num >= 2 + output[1] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] ); + #endif + #if stbir__coder_min_num >= 3 + output[2] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +#if ( stbir__coder_min_num == 4 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + do { + decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; + decode[1] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order1] ]; + decode[2] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order2] ]; + decode[3] = ( (float) input[stbir__decode_order3] ) * stbir__max_uint8_as_float_inverted; + input += 4; + decode += 4; + } while( decode < decode_end ); +} + + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__min_max_shift20( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup3( i0, i1, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i1, f1 ); + stbir__linear_to_srgb_finish( i2, f2 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + output += 16; + encode += 16; + + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float f; + STBIR_SIMD_NO_UNROLL(encode); + + output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); + output[stbir__decode_order1] = stbir__linear_to_srgb_uchar( encode[1] ); + output[stbir__decode_order2] = stbir__linear_to_srgb_uchar( encode[2] ); + + f = encode[3] * stbir__max_uint8_as_float + 0.5f; + STBIR_CLAMP(f, 0, 255); + output[stbir__decode_order3] = (unsigned char) f; + + output += 4; + encode += 4; + } while( output < end_output ); +} + +#endif + +#if ( stbir__coder_min_num == 2 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + decode += 4; + while( decode <= decode_end ) + { + decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; + decode[1-4] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; + decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0+2] ]; + decode[3-4] = ( (float) input[stbir__decode_order1+2] ) * stbir__max_uint8_as_float_inverted; + input += 4; + decode += 4; + } + decode -= 4; + if( decode < decode_end ) + { + decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ]; + decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; + } +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__scale_and_convert( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup2( i0, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i2, f2 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + output += 16; + encode += 16; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float f; + STBIR_SIMD_NO_UNROLL(encode); + + output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); + + f = encode[1] * stbir__max_uint8_as_float + 0.5f; + STBIR_CLAMP(f, 0, 255); + output[stbir__decode_order1] = (unsigned char) f; + + output += 2; + encode += 2; + } while( output < end_output ); +} + +#endif + +static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned short const * input = (unsigned short const *)inputp; + + #ifdef STBIR_SIMD + unsigned short const * end_input_m8 = input + width_times_channels - 8; + if ( width_times_channels >= 8 ) + { + decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o; + stbir__simdf8 of; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u16_to_u32( o, i ); + stbir__simdi8_convert_i32_to_float( of, o ); + stbir__simdf8_mult( of, of, STBIR_max_uint16_as_float_inverted8); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode + 0, of ); + #else + stbir__simdi i, o0, o1; + stbir__simdf of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u16_to_u32( o0,o1,i ); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted) ); + stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted)); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted; + decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted; + decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted; + decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint16_as_float_inverted; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted; + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + + +static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp; + unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + { + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdiX i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode ); + stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_pack_to_words( i, e0, e1 ); + stbir__simdiX_store( output, i ); + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e; + stbir__simdi i; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e, encode ); + stbir__simdf_madd( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), e ); + stbir__encode_simdf4_unflip( e ); + stbir__simdf_pack_to_8words( i, e, e ); // only use first 4 + stbir__simdi_store2( output-4, i ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + stbir__simdf e; + STBIR_NO_UNROLL(encode); + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_short( e ); + #if stbir__coder_min_num >= 2 + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_short( e ); + #endif + #if stbir__coder_min_num >= 3 + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_short( e ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + float f; + STBIR_SIMD_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f; + f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f; + f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f; + f = encode[stbir__encode_order3] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned short const * input = (unsigned short const *)inputp; + + #ifdef STBIR_SIMD + unsigned short const * end_input_m8 = input + width_times_channels - 8; + if ( width_times_channels >= 8 ) + { + decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o; + stbir__simdf8 of; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u16_to_u32( o, i ); + stbir__simdi8_convert_i32_to_float( of, o ); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode + 0, of ); + #else + stbir__simdi i, o0, o1; + stbir__simdf of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u16_to_u32( o0, o1, i ); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])); + decode[1-4] = ((float)(input[stbir__decode_order1])); + decode[2-4] = ((float)(input[stbir__decode_order2])); + decode[3-4] = ((float)(input[stbir__decode_order3])); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])); + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp; + unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + { + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdiX i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode ); + stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_pack_to_words( i, e0, e1 ); + stbir__simdiX_store( output, i ); + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e; + stbir__simdi i; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e, encode ); + stbir__simdf_add( e, STBIR__CONSTF(STBIR_simd_point5), e ); + stbir__encode_simdf4_unflip( e ); + stbir__simdf_pack_to_8words( i, e, e ); // only use first 4 + stbir__simdi_store2( output-4, i ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + float f; + STBIR_SIMD_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f; + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f; + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f; + f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + stbir__FP16 const * input = (stbir__FP16 const *)inputp; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 8 ) + { + stbir__FP16 const * end_input_m8 = input + width_times_channels - 8; + decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_NO_UNROLL(decode); + + stbir__half_to_float_SIMD( decode, input ); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of; + stbir__simdf8_load( of, decode ); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode, of ); + } + #else + { + stbir__simdf of0,of1; + stbir__simdf_load( of0, decode ); + stbir__simdf_load( of1, decode+4 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode, of0 ); + stbir__simdf_store( decode+4, of1 ); + } + #endif + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = stbir__half_to_float(input[stbir__decode_order0]); + decode[1-4] = stbir__half_to_float(input[stbir__decode_order1]); + decode[2-4] = stbir__half_to_float(input[stbir__decode_order2]); + decode[3-4] = stbir__half_to_float(input[stbir__decode_order3]); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = stbir__half_to_float(input[stbir__decode_order0]); + #if stbir__coder_min_num >= 2 + decode[1] = stbir__half_to_float(input[stbir__decode_order1]); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = stbir__half_to_float(input[stbir__decode_order2]); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + stbir__FP16 STBIR_SIMD_STREAMOUT_PTR( * ) output = (stbir__FP16*) outputp; + stbir__FP16 * end_output = ( (stbir__FP16*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 8 ) + { + float const * end_encode_m8 = encode + width_times_channels - 8; + end_output -= 8; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_SIMD_NO_UNROLL(encode); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of; + stbir__simdf8_load( of, encode ); + stbir__encode_simdf8_unflip( of ); + stbir__float_to_half_SIMD( output, (float*)&of ); + } + #else + { + stbir__simdf of[2]; + stbir__simdf_load( of[0], encode ); + stbir__simdf_load( of[1], encode+4 ); + stbir__encode_simdf4_unflip( of[0] ); + stbir__encode_simdf4_unflip( of[1] ); + stbir__float_to_half_SIMD( output, (float*)of ); + } + #endif + #else + stbir__float_to_half_SIMD( output, encode ); + #endif + encode += 8; + output += 8; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 8 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + STBIR_SIMD_NO_UNROLL(output); + output[0-4] = stbir__float_to_half(encode[stbir__encode_order0]); + output[1-4] = stbir__float_to_half(encode[stbir__encode_order1]); + output[2-4] = stbir__float_to_half(encode[stbir__encode_order2]); + output[3-4] = stbir__float_to_half(encode[stbir__encode_order3]); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + STBIR_NO_UNROLL(output); + output[0] = stbir__float_to_half(encode[stbir__encode_order0]); + #if stbir__coder_min_num >= 2 + output[1] = stbir__float_to_half(encode[stbir__encode_order1]); + #endif + #if stbir__coder_min_num >= 3 + output[2] = stbir__float_to_half(encode[stbir__encode_order2]); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + #ifdef stbir__decode_swizzle + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + float const * input = (float const *)inputp; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 16 ) + { + float const * end_input_m16 = input + width_times_channels - 16; + decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_NO_UNROLL(decode); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of0,of1; + stbir__simdf8_load( of0, input ); + stbir__simdf8_load( of1, input+8 ); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode, of0 ); + stbir__simdf8_store( decode+8, of1 ); + } + #else + { + stbir__simdf of0,of1,of2,of3; + stbir__simdf_load( of0, input ); + stbir__simdf_load( of1, input+4 ); + stbir__simdf_load( of2, input+8 ); + stbir__simdf_load( of3, input+12 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode, of0 ); + stbir__simdf_store( decode+4, of1 ); + stbir__simdf_store( decode+8, of2 ); + stbir__simdf_store( decode+12, of3 ); + } + #endif + #endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = input[stbir__decode_order0]; + decode[1-4] = input[stbir__decode_order1]; + decode[2-4] = input[stbir__decode_order2]; + decode[3-4] = input[stbir__decode_order3]; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = input[stbir__decode_order0]; + #if stbir__coder_min_num >= 2 + decode[1] = input[stbir__decode_order1]; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = input[stbir__decode_order2]; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif + + #else + + if ( (void*)decodep != inputp ) + STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) ); + + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LO_CLAMP) && !defined(stbir__decode_swizzle) + + if ( (void*)outputp != (void*) encode ) + STBIR_MEMCPY( outputp, encode, width_times_channels * sizeof( float ) ); + + #else + + float STBIR_SIMD_STREAMOUT_PTR( * ) output = (float*) outputp; + float * end_output = ( (float*) output ) + width_times_channels; + + #ifdef STBIR_FLOAT_HIGH_CLAMP + #define stbir_scalar_hi_clamp( v ) if ( v > STBIR_FLOAT_HIGH_CLAMP ) v = STBIR_FLOAT_HIGH_CLAMP; + #else + #define stbir_scalar_hi_clamp( v ) + #endif + #ifdef STBIR_FLOAT_LOW_CLAMP + #define stbir_scalar_lo_clamp( v ) if ( v < STBIR_FLOAT_LOW_CLAMP ) v = STBIR_FLOAT_LOW_CLAMP; + #else + #define stbir_scalar_lo_clamp( v ) + #endif + + #ifdef STBIR_SIMD + + #ifdef STBIR_FLOAT_HIGH_CLAMP + const stbir__simdfX high_clamp = stbir__simdf_frepX(STBIR_FLOAT_HIGH_CLAMP); + #endif + #ifdef STBIR_FLOAT_LOW_CLAMP + const stbir__simdfX low_clamp = stbir__simdf_frepX(STBIR_FLOAT_LOW_CLAMP); + #endif + + if ( width_times_channels >= ( stbir__simdfX_float_count * 2 ) ) + { + float const * end_encode_m8 = encode + width_times_channels - ( stbir__simdfX_float_count * 2 ); + end_output -= ( stbir__simdfX_float_count * 2 ); + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_load( e0, encode ); + stbir__simdfX_load( e1, encode+stbir__simdfX_float_count ); +#ifdef STBIR_FLOAT_HIGH_CLAMP + stbir__simdfX_min( e0, e0, high_clamp ); + stbir__simdfX_min( e1, e1, high_clamp ); +#endif +#ifdef STBIR_FLOAT_LOW_CLAMP + stbir__simdfX_max( e0, e0, low_clamp ); + stbir__simdfX_max( e1, e1, low_clamp ); +#endif + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_store( output, e0 ); + stbir__simdfX_store( output+stbir__simdfX_float_count, e1 ); + encode += stbir__simdfX_float_count * 2; + output += stbir__simdfX_float_count * 2; + if ( output < end_output ) + continue; + if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); +#ifdef STBIR_FLOAT_HIGH_CLAMP + stbir__simdf_min( e0, e0, high_clamp ); +#endif +#ifdef STBIR_FLOAT_LOW_CLAMP + stbir__simdf_max( e0, e0, low_clamp ); +#endif + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_store( output-4, e0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + float e; + STBIR_SIMD_NO_UNROLL(encode); + e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0-4] = e; + e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1-4] = e; + e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2-4] = e; + e = encode[ stbir__encode_order3 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[3-4] = e; + output += 4; + encode += 4; + } + output -= 4; + + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float e; + STBIR_NO_UNROLL(encode); + e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0] = e; + #if stbir__coder_min_num >= 2 + e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1] = e; + #endif + #if stbir__coder_min_num >= 3 + e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2] = e; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #endif +} + +#undef stbir__decode_suffix +#undef stbir__decode_simdf8_flip +#undef stbir__decode_simdf4_flip +#undef stbir__decode_order0 +#undef stbir__decode_order1 +#undef stbir__decode_order2 +#undef stbir__decode_order3 +#undef stbir__encode_order0 +#undef stbir__encode_order1 +#undef stbir__encode_order2 +#undef stbir__encode_order3 +#undef stbir__encode_simdf8_unflip +#undef stbir__encode_simdf4_unflip +#undef stbir__encode_simdfX_unflip +#undef STBIR__CODER_NAME +#undef stbir__coder_min_num +#undef stbir__decode_swizzle +#undef stbir_scalar_hi_clamp +#undef stbir_scalar_lo_clamp +#undef STB_IMAGE_RESIZE_DO_CODERS + +#elif defined( STB_IMAGE_RESIZE_DO_VERTICALS) + +#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#define STBIR_chans( start, end ) STBIR_strs_join14(start,STBIR__vertical_channels,end,_cont) +#else +#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__vertical_channels,end) +#endif + +#if STBIR__vertical_channels >= 1 +#define stbIF0( code ) code +#else +#define stbIF0( code ) +#endif +#if STBIR__vertical_channels >= 2 +#define stbIF1( code ) code +#else +#define stbIF1( code ) +#endif +#if STBIR__vertical_channels >= 3 +#define stbIF2( code ) code +#else +#define stbIF2( code ) +#endif +#if STBIR__vertical_channels >= 4 +#define stbIF3( code ) code +#else +#define stbIF3( code ) +#endif +#if STBIR__vertical_channels >= 5 +#define stbIF4( code ) code +#else +#define stbIF4( code ) +#endif +#if STBIR__vertical_channels >= 6 +#define stbIF5( code ) code +#else +#define stbIF5( code ) +#endif +#if STBIR__vertical_channels >= 7 +#define stbIF6( code ) code +#else +#define stbIF6( code ) +#endif +#if STBIR__vertical_channels >= 8 +#define stbIF7( code ) code +#else +#define stbIF7( code ) +#endif + +static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** outputs, float const * vertical_coefficients, float const * input, float const * input_end ) +{ + stbIF0( float STBIR_SIMD_STREAMOUT_PTR( * ) output0 = outputs[0]; float c0s = vertical_coefficients[0]; ) + stbIF1( float STBIR_SIMD_STREAMOUT_PTR( * ) output1 = outputs[1]; float c1s = vertical_coefficients[1]; ) + stbIF2( float STBIR_SIMD_STREAMOUT_PTR( * ) output2 = outputs[2]; float c2s = vertical_coefficients[2]; ) + stbIF3( float STBIR_SIMD_STREAMOUT_PTR( * ) output3 = outputs[3]; float c3s = vertical_coefficients[3]; ) + stbIF4( float STBIR_SIMD_STREAMOUT_PTR( * ) output4 = outputs[4]; float c4s = vertical_coefficients[4]; ) + stbIF5( float STBIR_SIMD_STREAMOUT_PTR( * ) output5 = outputs[5]; float c5s = vertical_coefficients[5]; ) + stbIF6( float STBIR_SIMD_STREAMOUT_PTR( * ) output6 = outputs[6]; float c6s = vertical_coefficients[6]; ) + stbIF7( float STBIR_SIMD_STREAMOUT_PTR( * ) output7 = outputs[7]; float c7s = vertical_coefficients[7]; ) + + #ifdef STBIR_SIMD + { + stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); ) + stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); ) + stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); ) + stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); ) + stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); ) + stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) + stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) + stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) ) + { + stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; + STBIR_SIMD_NO_UNROLL(output0); + + stbir__simdfX_load( r0, input ); stbir__simdfX_load( r1, input+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input+(3*stbir__simdfX_float_count) ); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdfX_load( o0, output0 ); stbir__simdfX_load( o1, output0+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); + stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) + stbIF1( stbir__simdfX_load( o0, output1 ); stbir__simdfX_load( o1, output1+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output1+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); + stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) + stbIF2( stbir__simdfX_load( o0, output2 ); stbir__simdfX_load( o1, output2+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output2+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); + stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) + stbIF3( stbir__simdfX_load( o0, output3 ); stbir__simdfX_load( o1, output3+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output3+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); + stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) + stbIF4( stbir__simdfX_load( o0, output4 ); stbir__simdfX_load( o1, output4+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output4+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); + stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) + stbIF5( stbir__simdfX_load( o0, output5 ); stbir__simdfX_load( o1, output5+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output5+(2*stbir__simdfX_float_count)); stbir__simdfX_load( o3, output5+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); + stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) + stbIF6( stbir__simdfX_load( o0, output6 ); stbir__simdfX_load( o1, output6+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output6+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); + stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) + stbIF7( stbir__simdfX_load( o0, output7 ); stbir__simdfX_load( o1, output7+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output7+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); + stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) + #else + stbIF0( stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); + stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) + stbIF1( stbir__simdfX_mult( o0, r0, c1 ); stbir__simdfX_mult( o1, r1, c1 ); stbir__simdfX_mult( o2, r2, c1 ); stbir__simdfX_mult( o3, r3, c1 ); + stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) + stbIF2( stbir__simdfX_mult( o0, r0, c2 ); stbir__simdfX_mult( o1, r1, c2 ); stbir__simdfX_mult( o2, r2, c2 ); stbir__simdfX_mult( o3, r3, c2 ); + stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) + stbIF3( stbir__simdfX_mult( o0, r0, c3 ); stbir__simdfX_mult( o1, r1, c3 ); stbir__simdfX_mult( o2, r2, c3 ); stbir__simdfX_mult( o3, r3, c3 ); + stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) + stbIF4( stbir__simdfX_mult( o0, r0, c4 ); stbir__simdfX_mult( o1, r1, c4 ); stbir__simdfX_mult( o2, r2, c4 ); stbir__simdfX_mult( o3, r3, c4 ); + stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) + stbIF5( stbir__simdfX_mult( o0, r0, c5 ); stbir__simdfX_mult( o1, r1, c5 ); stbir__simdfX_mult( o2, r2, c5 ); stbir__simdfX_mult( o3, r3, c5 ); + stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) + stbIF6( stbir__simdfX_mult( o0, r0, c6 ); stbir__simdfX_mult( o1, r1, c6 ); stbir__simdfX_mult( o2, r2, c6 ); stbir__simdfX_mult( o3, r3, c6 ); + stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) + stbIF7( stbir__simdfX_mult( o0, r0, c7 ); stbir__simdfX_mult( o1, r1, c7 ); stbir__simdfX_mult( o2, r2, c7 ); stbir__simdfX_mult( o3, r3, c7 ); + stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) + #endif + + input += (4*stbir__simdfX_float_count); + stbIF0( output0 += (4*stbir__simdfX_float_count); ) stbIF1( output1 += (4*stbir__simdfX_float_count); ) stbIF2( output2 += (4*stbir__simdfX_float_count); ) stbIF3( output3 += (4*stbir__simdfX_float_count); ) stbIF4( output4 += (4*stbir__simdfX_float_count); ) stbIF5( output5 += (4*stbir__simdfX_float_count); ) stbIF6( output6 += (4*stbir__simdfX_float_count); ) stbIF7( output7 += (4*stbir__simdfX_float_count); ) + } + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= 16 ) + { + stbir__simdf o0, r0; + STBIR_SIMD_NO_UNROLL(output0); + + stbir__simdf_load( r0, input ); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdf_load( o0, output0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); stbir__simdf_store( output0, o0 ); ) + stbIF1( stbir__simdf_load( o0, output1 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); stbir__simdf_store( output1, o0 ); ) + stbIF2( stbir__simdf_load( o0, output2 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); stbir__simdf_store( output2, o0 ); ) + stbIF3( stbir__simdf_load( o0, output3 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); stbir__simdf_store( output3, o0 ); ) + stbIF4( stbir__simdf_load( o0, output4 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); stbir__simdf_store( output4, o0 ); ) + stbIF5( stbir__simdf_load( o0, output5 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); stbir__simdf_store( output5, o0 ); ) + stbIF6( stbir__simdf_load( o0, output6 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) + stbIF7( stbir__simdf_load( o0, output7 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) + #else + stbIF0( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); stbir__simdf_store( output0, o0 ); ) + stbIF1( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); stbir__simdf_store( output1, o0 ); ) + stbIF2( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); stbir__simdf_store( output2, o0 ); ) + stbIF3( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); stbir__simdf_store( output3, o0 ); ) + stbIF4( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); stbir__simdf_store( output4, o0 ); ) + stbIF5( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); stbir__simdf_store( output5, o0 ); ) + stbIF6( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) + stbIF7( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) + #endif + + input += 4; + stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) + } + } + #else + STBIR_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= 16 ) + { + float r0, r1, r2, r3; + STBIR_NO_UNROLL(input); + + r0 = input[0], r1 = input[1], r2 = input[2], r3 = input[3]; + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( output0[0] += ( r0 * c0s ); output0[1] += ( r1 * c0s ); output0[2] += ( r2 * c0s ); output0[3] += ( r3 * c0s ); ) + stbIF1( output1[0] += ( r0 * c1s ); output1[1] += ( r1 * c1s ); output1[2] += ( r2 * c1s ); output1[3] += ( r3 * c1s ); ) + stbIF2( output2[0] += ( r0 * c2s ); output2[1] += ( r1 * c2s ); output2[2] += ( r2 * c2s ); output2[3] += ( r3 * c2s ); ) + stbIF3( output3[0] += ( r0 * c3s ); output3[1] += ( r1 * c3s ); output3[2] += ( r2 * c3s ); output3[3] += ( r3 * c3s ); ) + stbIF4( output4[0] += ( r0 * c4s ); output4[1] += ( r1 * c4s ); output4[2] += ( r2 * c4s ); output4[3] += ( r3 * c4s ); ) + stbIF5( output5[0] += ( r0 * c5s ); output5[1] += ( r1 * c5s ); output5[2] += ( r2 * c5s ); output5[3] += ( r3 * c5s ); ) + stbIF6( output6[0] += ( r0 * c6s ); output6[1] += ( r1 * c6s ); output6[2] += ( r2 * c6s ); output6[3] += ( r3 * c6s ); ) + stbIF7( output7[0] += ( r0 * c7s ); output7[1] += ( r1 * c7s ); output7[2] += ( r2 * c7s ); output7[3] += ( r3 * c7s ); ) + #else + stbIF0( output0[0] = ( r0 * c0s ); output0[1] = ( r1 * c0s ); output0[2] = ( r2 * c0s ); output0[3] = ( r3 * c0s ); ) + stbIF1( output1[0] = ( r0 * c1s ); output1[1] = ( r1 * c1s ); output1[2] = ( r2 * c1s ); output1[3] = ( r3 * c1s ); ) + stbIF2( output2[0] = ( r0 * c2s ); output2[1] = ( r1 * c2s ); output2[2] = ( r2 * c2s ); output2[3] = ( r3 * c2s ); ) + stbIF3( output3[0] = ( r0 * c3s ); output3[1] = ( r1 * c3s ); output3[2] = ( r2 * c3s ); output3[3] = ( r3 * c3s ); ) + stbIF4( output4[0] = ( r0 * c4s ); output4[1] = ( r1 * c4s ); output4[2] = ( r2 * c4s ); output4[3] = ( r3 * c4s ); ) + stbIF5( output5[0] = ( r0 * c5s ); output5[1] = ( r1 * c5s ); output5[2] = ( r2 * c5s ); output5[3] = ( r3 * c5s ); ) + stbIF6( output6[0] = ( r0 * c6s ); output6[1] = ( r1 * c6s ); output6[2] = ( r2 * c6s ); output6[3] = ( r3 * c6s ); ) + stbIF7( output7[0] = ( r0 * c7s ); output7[1] = ( r1 * c7s ); output7[2] = ( r2 * c7s ); output7[3] = ( r3 * c7s ); ) + #endif + + input += 4; + stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) + } + #endif + STBIR_NO_UNROLL_LOOP_START + while ( input < input_end ) + { + float r = input[0]; + STBIR_NO_UNROLL(output0); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( output0[0] += ( r * c0s ); ) + stbIF1( output1[0] += ( r * c1s ); ) + stbIF2( output2[0] += ( r * c2s ); ) + stbIF3( output3[0] += ( r * c3s ); ) + stbIF4( output4[0] += ( r * c4s ); ) + stbIF5( output5[0] += ( r * c5s ); ) + stbIF6( output6[0] += ( r * c6s ); ) + stbIF7( output7[0] += ( r * c7s ); ) + #else + stbIF0( output0[0] = ( r * c0s ); ) + stbIF1( output1[0] = ( r * c1s ); ) + stbIF2( output2[0] = ( r * c2s ); ) + stbIF3( output3[0] = ( r * c3s ); ) + stbIF4( output4[0] = ( r * c4s ); ) + stbIF5( output5[0] = ( r * c5s ); ) + stbIF6( output6[0] = ( r * c6s ); ) + stbIF7( output7[0] = ( r * c7s ); ) + #endif + + ++input; + stbIF0( ++output0; ) stbIF1( ++output1; ) stbIF2( ++output2; ) stbIF3( ++output3; ) stbIF4( ++output4; ) stbIF5( ++output5; ) stbIF6( ++output6; ) stbIF7( ++output7; ) + } +} + +static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, float const * vertical_coefficients, float const ** inputs, float const * input0_end ) +{ + float STBIR_SIMD_STREAMOUT_PTR( * ) output = outputp; + + stbIF0( float const * input0 = inputs[0]; float c0s = vertical_coefficients[0]; ) + stbIF1( float const * input1 = inputs[1]; float c1s = vertical_coefficients[1]; ) + stbIF2( float const * input2 = inputs[2]; float c2s = vertical_coefficients[2]; ) + stbIF3( float const * input3 = inputs[3]; float c3s = vertical_coefficients[3]; ) + stbIF4( float const * input4 = inputs[4]; float c4s = vertical_coefficients[4]; ) + stbIF5( float const * input5 = inputs[5]; float c5s = vertical_coefficients[5]; ) + stbIF6( float const * input6 = inputs[6]; float c6s = vertical_coefficients[6]; ) + stbIF7( float const * input7 = inputs[7]; float c7s = vertical_coefficients[7]; ) + +#if ( STBIR__vertical_channels == 1 ) && !defined(STB_IMAGE_RESIZE_VERTICAL_CONTINUE) + // check single channel one weight + if ( ( c0s >= (1.0f-0.000001f) ) && ( c0s <= (1.0f+0.000001f) ) ) + { + STBIR_MEMCPY( output, input0, (char*)input0_end - (char*)input0 ); + return; + } +#endif + + #ifdef STBIR_SIMD + { + stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); ) + stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); ) + stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); ) + stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); ) + stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); ) + stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) + stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) + stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) + + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) ) + { + stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; + STBIR_SIMD_NO_UNROLL(output); + + // prefetch four loop iterations ahead (doesn't affect much for small resizes, but helps with big ones) + stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); ) + stbIF1( stbir__prefetch( input1 + (16*stbir__simdfX_float_count) ); ) + stbIF2( stbir__prefetch( input2 + (16*stbir__simdfX_float_count) ); ) + stbIF3( stbir__prefetch( input3 + (16*stbir__simdfX_float_count) ); ) + stbIF4( stbir__prefetch( input4 + (16*stbir__simdfX_float_count) ); ) + stbIF5( stbir__prefetch( input5 + (16*stbir__simdfX_float_count) ); ) + stbIF6( stbir__prefetch( input6 + (16*stbir__simdfX_float_count) ); ) + stbIF7( stbir__prefetch( input7 + (16*stbir__simdfX_float_count) ); ) + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdfX_load( o0, output ); stbir__simdfX_load( o1, output+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output+(3*stbir__simdfX_float_count) ); + stbir__simdfX_load( r0, input0 ); stbir__simdfX_load( r1, input0+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); ) + #else + stbIF0( stbir__simdfX_load( r0, input0 ); stbir__simdfX_load( r1, input0+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); ) + #endif + + stbIF1( stbir__simdfX_load( r0, input1 ); stbir__simdfX_load( r1, input1+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input1+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); ) + stbIF2( stbir__simdfX_load( r0, input2 ); stbir__simdfX_load( r1, input2+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input2+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); ) + stbIF3( stbir__simdfX_load( r0, input3 ); stbir__simdfX_load( r1, input3+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input3+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); ) + stbIF4( stbir__simdfX_load( r0, input4 ); stbir__simdfX_load( r1, input4+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input4+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); ) + stbIF5( stbir__simdfX_load( r0, input5 ); stbir__simdfX_load( r1, input5+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input5+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input5+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); ) + stbIF6( stbir__simdfX_load( r0, input6 ); stbir__simdfX_load( r1, input6+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input6+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); ) + stbIF7( stbir__simdfX_load( r0, input7 ); stbir__simdfX_load( r1, input7+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input7+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); ) + + stbir__simdfX_store( output, o0 ); stbir__simdfX_store( output+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output+(3*stbir__simdfX_float_count), o3 ); + output += (4*stbir__simdfX_float_count); + stbIF0( input0 += (4*stbir__simdfX_float_count); ) stbIF1( input1 += (4*stbir__simdfX_float_count); ) stbIF2( input2 += (4*stbir__simdfX_float_count); ) stbIF3( input3 += (4*stbir__simdfX_float_count); ) stbIF4( input4 += (4*stbir__simdfX_float_count); ) stbIF5( input5 += (4*stbir__simdfX_float_count); ) stbIF6( input6 += (4*stbir__simdfX_float_count); ) stbIF7( input7 += (4*stbir__simdfX_float_count); ) + } + + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + { + stbir__simdf o0, r0; + STBIR_SIMD_NO_UNROLL(output); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdf_load( o0, output ); stbir__simdf_load( r0, input0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); ) + #else + stbIF0( stbir__simdf_load( r0, input0 ); stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); ) + #endif + stbIF1( stbir__simdf_load( r0, input1 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); ) + stbIF2( stbir__simdf_load( r0, input2 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); ) + stbIF3( stbir__simdf_load( r0, input3 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); ) + stbIF4( stbir__simdf_load( r0, input4 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); ) + stbIF5( stbir__simdf_load( r0, input5 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); ) + stbIF6( stbir__simdf_load( r0, input6 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); ) + stbIF7( stbir__simdf_load( r0, input7 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); ) + + stbir__simdf_store( output, o0 ); + output += 4; + stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) + } + } + #else + STBIR_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + { + float o0, o1, o2, o3; + STBIR_NO_UNROLL(output); + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( o0 = output[0] + input0[0] * c0s; o1 = output[1] + input0[1] * c0s; o2 = output[2] + input0[2] * c0s; o3 = output[3] + input0[3] * c0s; ) + #else + stbIF0( o0 = input0[0] * c0s; o1 = input0[1] * c0s; o2 = input0[2] * c0s; o3 = input0[3] * c0s; ) + #endif + stbIF1( o0 += input1[0] * c1s; o1 += input1[1] * c1s; o2 += input1[2] * c1s; o3 += input1[3] * c1s; ) + stbIF2( o0 += input2[0] * c2s; o1 += input2[1] * c2s; o2 += input2[2] * c2s; o3 += input2[3] * c2s; ) + stbIF3( o0 += input3[0] * c3s; o1 += input3[1] * c3s; o2 += input3[2] * c3s; o3 += input3[3] * c3s; ) + stbIF4( o0 += input4[0] * c4s; o1 += input4[1] * c4s; o2 += input4[2] * c4s; o3 += input4[3] * c4s; ) + stbIF5( o0 += input5[0] * c5s; o1 += input5[1] * c5s; o2 += input5[2] * c5s; o3 += input5[3] * c5s; ) + stbIF6( o0 += input6[0] * c6s; o1 += input6[1] * c6s; o2 += input6[2] * c6s; o3 += input6[3] * c6s; ) + stbIF7( o0 += input7[0] * c7s; o1 += input7[1] * c7s; o2 += input7[2] * c7s; o3 += input7[3] * c7s; ) + output[0] = o0; output[1] = o1; output[2] = o2; output[3] = o3; + output += 4; + stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) + } + #endif + STBIR_NO_UNROLL_LOOP_START + while ( input0 < input0_end ) + { + float o0; + STBIR_NO_UNROLL(output); + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( o0 = output[0] + input0[0] * c0s; ) + #else + stbIF0( o0 = input0[0] * c0s; ) + #endif + stbIF1( o0 += input1[0] * c1s; ) + stbIF2( o0 += input2[0] * c2s; ) + stbIF3( o0 += input3[0] * c3s; ) + stbIF4( o0 += input4[0] * c4s; ) + stbIF5( o0 += input5[0] * c5s; ) + stbIF6( o0 += input6[0] * c6s; ) + stbIF7( o0 += input7[0] * c7s; ) + output[0] = o0; + ++output; + stbIF0( ++input0; ) stbIF1( ++input1; ) stbIF2( ++input2; ) stbIF3( ++input3; ) stbIF4( ++input4; ) stbIF5( ++input5; ) stbIF6( ++input6; ) stbIF7( ++input7; ) + } +} + +#undef stbIF0 +#undef stbIF1 +#undef stbIF2 +#undef stbIF3 +#undef stbIF4 +#undef stbIF5 +#undef stbIF6 +#undef stbIF7 +#undef STB_IMAGE_RESIZE_DO_VERTICALS +#undef STBIR__vertical_channels +#undef STB_IMAGE_RESIZE_DO_HORIZONTALS +#undef STBIR_strs_join24 +#undef STBIR_strs_join14 +#undef STBIR_chans +#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#undef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#endif + +#else // !STB_IMAGE_RESIZE_DO_VERTICALS + +#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__horizontal_channels,end) + +#ifndef stbir__2_coeff_only +#define stbir__2_coeff_only() \ + stbir__1_coeff_only(); \ + stbir__1_coeff_remnant(1); +#endif + +#ifndef stbir__2_coeff_remnant +#define stbir__2_coeff_remnant( ofs ) \ + stbir__1_coeff_remnant(ofs); \ + stbir__1_coeff_remnant((ofs)+1); +#endif + +#ifndef stbir__3_coeff_only +#define stbir__3_coeff_only() \ + stbir__2_coeff_only(); \ + stbir__1_coeff_remnant(2); +#endif + +#ifndef stbir__3_coeff_remnant +#define stbir__3_coeff_remnant( ofs ) \ + stbir__2_coeff_remnant(ofs); \ + stbir__1_coeff_remnant((ofs)+2); +#endif + +#ifndef stbir__3_coeff_setup +#define stbir__3_coeff_setup() +#endif + +#ifndef stbir__4_coeff_start +#define stbir__4_coeff_start() \ + stbir__2_coeff_only(); \ + stbir__2_coeff_remnant(2); +#endif + +#ifndef stbir__4_coeff_continue_from_4 +#define stbir__4_coeff_continue_from_4( ofs ) \ + stbir__2_coeff_remnant(ofs); \ + stbir__2_coeff_remnant((ofs)+2); +#endif + +#ifndef stbir__store_output_tiny +#define stbir__store_output_tiny stbir__store_output +#endif + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_1_coeff)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__1_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_2_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__2_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_3_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__3_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_4_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_5_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__1_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_6_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__2_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_7_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + stbir__3_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_8_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_9_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__1_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_10_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__2_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_11_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__3_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_12_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__4_coeff_continue_from_4(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod0 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod1 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__1_coeff_remnant( 4 ); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod2 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__2_coeff_remnant( 4 ); + + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__3_coeff_remnant( 4 ); + + stbir__store_output(); + } while ( output < output_end ); +} + +static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_funcs)[4]= +{ + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3), +}; + +static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_funcs)[12]= +{ + STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff), + STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_3_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_7_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs), +}; + +#undef STBIR__horizontal_channels +#undef STB_IMAGE_RESIZE_DO_HORIZONTALS +#undef stbir__1_coeff_only +#undef stbir__1_coeff_remnant +#undef stbir__2_coeff_only +#undef stbir__2_coeff_remnant +#undef stbir__3_coeff_only +#undef stbir__3_coeff_remnant +#undef stbir__3_coeff_setup +#undef stbir__4_coeff_start +#undef stbir__4_coeff_continue_from_4 +#undef stbir__store_output +#undef stbir__store_output_tiny +#undef STBIR_chans + +#endif // HORIZONALS + +#undef STBIR_strs_join2 +#undef STBIR_strs_join1 + +#endif // STB_IMAGE_RESIZE_DO_HORIZONTALS/VERTICALS/CODERS + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +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. +------------------------------------------------------------------------------ +*/ diff --git a/src/mlpack/core/stb/bundled/stb_image_write.h b/src/mlpack/core/stb/bundled/stb_image_write.h new file mode 100644 index 0000000000..e4b32ed1bc --- /dev/null +++ b/src/mlpack/core/stb/bundled/stb_image_write.h @@ -0,0 +1,1724 @@ +/* stb_image_write - v1.16 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. + +USAGE: + + There are five functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + Andrew Kensler + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +STBIWDEF int stbi_write_tga_with_rle; +STBIWDEF int stbi_write_png_compression_level; +STBIWDEF int stbi_write_force_png_filter; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBIW_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +static int stbi__flip_vertically_on_write = 0; + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + +typedef struct +{ + stbi_write_func *func; + void *context; + unsigned char buffer[64]; + int buf_used; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write_flush(stbi__write_context *s) +{ + if (s->buf_used) { + s->func(s->context, &s->buffer, s->buf_used); + s->buf_used = 0; + } +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write1(stbi__write_context *s, unsigned char a) +{ + if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) + stbiw__write_flush(s); + s->buffer[s->buf_used++] = a; +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + int n; + if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) + stbiw__write_flush(s); + n = s->buf_used; + s->buf_used = n+3; + s->buffer[n+0] = a; + s->buffer[n+1] = b; + s->buffer[n+2] = c; +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + stbiw__write1(s, d[comp - 1]); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + stbiw__write1(s, d[0]); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + stbiw__write1(s, d[comp - 1]); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + stbiw__write_flush(s); + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + if (comp != 4) { + // write RGB bitmap + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + } else { + // RGBA bitmaps need a v4 header + // use BI_BITFIELDS mode with 32bpp and alpha mask + // (straight BI_RGB with alpha mask doesn't work in most readers) + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0, + "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444", + 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header + 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header + } +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + stbiw__write1(s, header); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + stbiw__write1(s, header); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + stbiw__write_flush(s); + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +#ifndef STBI_WRITE_NO_STDIO + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +#ifdef __STDC_LIB_EXT1__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (void *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + // store uncompressed instead if compression was worse + if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { + stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 + for (j = 0; j < data_len;) { + int blocklen = data_len - j; + if (blocklen > 32767) blocklen = 32767; + stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression + stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN + stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN + stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); + memcpy(out+stbiw__sbn(out), data+j, blocklen); + stbiw__sbn(out) += blocklen; + j += blocklen; + } + } + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +#endif +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k, subsample; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + subsample = quality <= 90 ? 1 : 0; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + const unsigned char *dataR = (const unsigned char *)data; + const unsigned char *dataG = dataR + ofsG; + const unsigned char *dataB = dataR + ofsB; + int x, y, pos; + if(subsample) { + for(y = 0; y < height; y += 16) { + for(x = 0; x < width; x += 16) { + float Y[256], U[256], V[256]; + for(row = y, pos = 0; row < y+16; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+16; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + + // subsample U,V + { + float subU[64], subV[64]; + int yy, xx; + for(yy = 0, pos = 0; yy < 8; ++yy) { + for(xx = 0; xx < 8; ++xx, ++pos) { + int j = yy*32+xx*2; + subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f; + subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f; + } + } + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + } else { + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float Y[64], U[64], V[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.16 (2021-07-11) + make Deflate code emit uncompressed blocks when it would otherwise expand + support writing BMPs with alpha channel + 1.15 (2020-07-13) unknown + 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels + 1.13 + 1.12 + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +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. +------------------------------------------------------------------------------ +*/ diff --git a/src/mlpack/core/stb/stb.hpp b/src/mlpack/core/stb/stb.hpp new file mode 100644 index 0000000000..e9dd0d78ad --- /dev/null +++ b/src/mlpack/core/stb/stb.hpp @@ -0,0 +1,85 @@ +/** + * @file core/data/stb.hpp + * @author Omar Shrit + * + * Header to include stb in mlpack, in addition to allow the user to disable + * all of these includes. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MLPACK_CORE_STB_STB_HPP +#define MLPACK_CORE_STB_STB_HPP + +#ifndef STB_IMAGE_STATIC + #define STB_IMAGE_STATIC +#endif + +#ifndef STB_IMAGE_WRITE_STATIC + #define STB_IMAGE_WRITE_STATIC +#endif + +#ifndef STB_IMAGE_RESIZE_STATIC + #define STB_IMAGE_RESIZE_STATIC +#endif + +#ifndef STB_IMAGE_IMPLEMENTATION + #define STB_IMAGE_IMPLEMENTATION +#endif + +#ifndef STB_IMAGE_WRITE_IMPLEMENTATION + #define STB_IMAGE_WRITE_IMPLEMENTATION +#endif + +#ifndef STB_IMAGE_RESIZE_IMPLEMENTATION + #define STB_IMAGE_RESIZE_IMPLEMENTATION +#endif + +#if defined(MLPACK_USE_SYSTEM_STB) + +#if defined __has_include + #if __has_include() + #include + #elif __has_include() + #include + #else + #pragma warning("System's STB not found; including bundled STB") + #include "bundled/stb_image.h" + #endif +#endif + +#if defined __has_include + #if __has_include() + #include + #elif __has_include() + #include + #else + #pragma warning("System's STB not found; including bundled STB") + #include "bundled/stb_image_write.h" + #endif +#endif + +#if defined __has_include + #if __has_include() + #include + #elif __has_include() + #include + #else + #pragma warning("System's STB not found; including bundled STB") + #include "bundled/stb_image_resize2.h" + #endif +#endif + +#else + +// Now include STB headers +#include "bundled/stb_image.h" +#include "bundled/stb_image_write.h" +#include "bundled/stb_image_resize2.h" + +#endif + +#endif diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index e4d454cbda..834232fa32 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -68,7 +68,7 @@ add_executable(mlpack_test hpt_test.cpp hoeffding_tree_test.cpp hyperplane_test.cpp - image_load_test.cpp + image_test.cpp imputation_test.cpp io_test.cpp kde_model_test.cpp @@ -269,6 +269,7 @@ add_custom_command(TARGET mlpack_test COMMAND ${CMAKE_COMMAND} -E tar xjf digits_test.tar.bz2 COMMAND ${CMAKE_COMMAND} -E tar xjf digits_train_label.tar.bz2 COMMAND ${CMAKE_COMMAND} -E tar xjf digits_test_label.tar.bz2 + COMMAND ${CMAKE_COMMAND} -E tar xjf sheep.tar.bz2 WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ) diff --git a/src/mlpack/tests/data/sheep.tar.bz2 b/src/mlpack/tests/data/sheep.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..77b08e82364ac325183b3fcb8a6ca30aa28f4513 GIT binary patch literal 668234 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 z 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%0DR1sS7ANQHQS!3aHAN4 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 JfIZV2kZlrl~Ga&hkUkY8$J<0DoO= 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
|J(t1 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 matrix; data::ImageInfo info; - REQUIRE_THROWS_AS(data::Load("invalidExtendion.p4ng", matrix, info, + REQUIRE_THROWS_AS(data::Load("invalidExtension.p4ng", matrix, info, true), std::runtime_error); } @@ -152,4 +150,89 @@ TEST_CASE("ImageInfoSerialization", "[ImageLoadTest]") REQUIRE(info.Quality() == binaryInfo.Quality()); } -#endif // MLPACK_HAS_STB. +/** + * Test resize the image if this is done correctly. Try it with a few different + * types. + */ +TEMPLATE_TEST_CASE("ImagesResizeTest", "[ImageTest]", unsigned char, size_t, + float, double) +{ + typedef TestType eT; + + arma::Mat image, images; + data::ImageInfo info, resizedInfo, resizedInfo2; + std::vector files = + {"sheep_1.jpg", "sheep_2.jpg", "sheep_3.jpg", "sheep_4.jpg", + "sheep_5.jpg", "sheep_6.jpg"}; + std::vector reSheeps = + {"re_sheep_1.jpg", "re_sheep_2.jpg", "re_sheep_3.jpg", "re_sheep_4.jpg", + "re_sheep_5.jpg", "re_sheep_6.jpg"}; + std::vector smSheeps = + {"sm_sheep_1.jpg", "sm_sheep_2.jpg", "sm_sheep_3.jpg", "sm_sheep_4.jpg", + "sm_sheep_5.jpg", "sm_sheep_6.jpg"}; + + // Load and Resize each one of them individually, because they do not have + // the same sizes, and then the resized images, will be used in the next + // test. + for (size_t i = 0; i < files.size(); i++) + { + REQUIRE(data::Load(files.at(i), image, info, false) == true); + ResizeImages(image, info, 320, 320); + REQUIRE(data::Save(reSheeps.at(i), image, info, false) == true); + } + + // Since they are all resized, this should passes + REQUIRE(data::Load(reSheeps, images, resizedInfo, false) == true); + + REQUIRE(info.Width() == resizedInfo.Width()); + REQUIRE(info.Height() == resizedInfo.Height()); + + REQUIRE(data::Load(reSheeps, images, info, false) == true); + + ResizeImages(images, info, 160, 160); + + REQUIRE(data::Save(smSheeps, images, info, false) == true); + + REQUIRE(data::Load(smSheeps, images, resizedInfo2, false) == true); + + REQUIRE(info.Width() == resizedInfo2.Width()); + REQUIRE(info.Height() == resizedInfo2.Height()); + + // cleanup generated images. + for (size_t i = 0; i < reSheeps.size(); ++i) + { + remove(reSheeps.at(i).c_str()); + remove(smSheeps.at(i).c_str()); + } +} + +/** + * Test if we resize to the same original dimension we will get the same pixels + * and no modification to the image. Try it with a few different types. + */ +TEMPLATE_TEST_CASE("IdenticalResizeTest", "[ImageTest]", unsigned char, size_t, + float, double) +{ + typedef TestType eT; + + arma::Mat image; + data::ImageInfo info; + std::vector files = + {"sheep_1.jpg", "sheep_2.jpg", "sheep_3.jpg", "sheep_4.jpg", + "sheep_5.jpg", "sheep_6.jpg"}; + + for (size_t i = 0; i < files.size(); i++) + { + REQUIRE(data::Load(files.at(i), image, info, false) == true); + arma::Mat originalImage = image; + ResizeImages(image, info, info.Width(), info.Height()); + for (size_t i = 0; i < originalImage.n_rows; ++i) + { + for (size_t j = 0; j < originalImage.n_cols; ++j) + { + REQUIRE(originalImage.at(i, j) == image.at(i, j)); + } + } + } +} + diff --git a/src/mlpack/tests/main_tests/image_converter_test.cpp b/src/mlpack/tests/main_tests/image_converter_test.cpp index 3d12986bfa..5fcdc41562 100644 --- a/src/mlpack/tests/main_tests/image_converter_test.cpp +++ b/src/mlpack/tests/main_tests/image_converter_test.cpp @@ -22,8 +22,6 @@ using namespace mlpack; -#ifdef MLPACK_HAS_STB // Compile this only if stb is present. - BINDING_TEST_FIXTURE(ImageConverterTestFixture); TEST_CASE_METHOD(ImageConverterTestFixture, "LoadImageTest", @@ -164,5 +162,3 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "EmptyInputTest", REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); } - -#endif // MLPACK_HAS_STB.

X_vu|aOiD^%b7+4F=4hKTB(HDcBf2n|ZH*3A1 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%0AWH& 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