diff --git a/libs/yocto/CMakeLists.txt b/libs/yocto/CMakeLists.txt index 7474cf781..4b6d79021 100644 --- a/libs/yocto/CMakeLists.txt +++ b/libs/yocto/CMakeLists.txt @@ -1,10 +1,10 @@ add_library(yocto STATIC yocto_math.h + yocto_image.h yocto_sampling.h yocto_shading.h yocto_modeling.h yocto_animation.h yocto_raycasting.h yocto_raycasting.cpp yocto_shape.h yocto_shape.cpp - yocto_image.h yocto_image.cpp yocto_scene.h yocto_scene.cpp yocto_trace.h yocto_trace.cpp yocto_modelio.h yocto_modelio.cpp diff --git a/libs/yocto/yocto_image.cpp b/libs/yocto/yocto_image.cpp deleted file mode 100644 index 3060dde74..000000000 --- a/libs/yocto/yocto_image.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// -// Implementation for Yocto/Image. -// - -// -// LICENSE: -// -// Copyright (c) 2016 -- 2022 Fabio Pellacini -// -// 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. -// - -// ----------------------------------------------------------------------------- -// INCLUDES -// ----------------------------------------------------------------------------- - -#include "yocto_image.h" - -#include - -#include -#include - -// ----------------------------------------------------------------------------- -// USING DIRECTIVES -// ----------------------------------------------------------------------------- -namespace yocto { - -// using directives -using std::unique_ptr; - -} // namespace yocto - -// ----------------------------------------------------------------------------- -// IMPLEMENTATION OF IMAGE OPERATIONS -// ----------------------------------------------------------------------------- -namespace yocto { - -// Conversion from/to floats. -image_t byte_to_float(const image_t& bt) { - return transform_image(bt, [](vec4b a) { return byte_to_float(a); }); -} -image_t float_to_byte(const image_t& fl) { - return transform_image(fl, [](vec4f a) { return float_to_byte(a); }); -} - -// Conversion between linear and gamma-encoded images. -image_t srgb_to_rgb(const image_t& srgb) { - return transform_image(srgb, [](vec4f a) { return srgb_to_rgb(a); }); -} -image_t rgb_to_srgb(const image_t& rgb) { - return transform_image(rgb, [](vec4f a) { return rgb_to_srgb(a); }); -} -image_t srgbb_to_rgb(const image_t& srgb) { - return transform_image(srgb, [](vec4b a) { return srgbb_to_rgb(a); }); -} -image_t rgb_to_srgbb(const image_t& rgb) { - return transform_image(rgb, [](vec4f a) { return rgb_to_srgbb(a); }); -} - -// Apply exposure and filmic tone mapping -image_t tonemap_image( - const image_t& hdr, float exposure, bool filmic, bool srgb) { - return transform_image(hdr, [exposure, filmic, srgb](vec4f a) { - return tonemap(a, exposure, filmic, srgb); - }); -} -image_t tonemapb_image( - const image_t& hdr, float exposure, bool filmic, bool srgb) { - return transform_image(hdr, [exposure, filmic, srgb](vec4f a) { - return float_to_byte(tonemap(a, exposure, filmic, srgb)); - }); -} -void tonemap_image(image_t& ldr, const image_t& hdr, - float exposure, bool filmic, bool srgb) { - return transform_image(ldr, hdr, [exposure, filmic, srgb](vec4f a) { - return tonemap(a, exposure, filmic, srgb); - }); -} - -// Apply exposure and filmic tone mapping -image_t colorgrade_image( - const image_t& img, bool linear, const colorgrade_params& params) { - return transform_image( - img, [linear, params](vec4f a) { return colorgrade(a, linear, params); }); -} -void colorgrade_image(image_t& graded, const image_t& img, - bool linear, const colorgrade_params& params) { - return transform_image(graded, img, - [linear, params](vec4f a) { return colorgrade(a, linear, params); }); -} - -// compute white balance -vec3f compute_white_balance(const image_t& img) { - auto rgb = vec3f{0, 0, 0}; - for (auto& p : img) rgb += xyz(p); - if (rgb == vec3f{0, 0, 0}) return {0, 0, 0}; - return rgb / max(rgb); -} - -// image compositing -image_t composite_image( - const image_t& foreground, const image_t& background) { - return transform_images( - foreground, background, [](vec4f a, vec4f b) { return composite(a, b); }); -} - -// removes alpha -image_t remove_alpha(const image_t& img) { - return transform_image(img, [](vec4f a) -> vec4f { return {xyz(a), 1}; }); -} - -// turns alpha into a gray scale image -image_t alpha_to_gray(const image_t& img) { - return transform_image(img, [](vec4f a) -> vec4f { - auto g = a.w; - return {g, g, g, 1}; - }); -} - -image_t image_difference( - const image_t& a, const image_t& b, bool display) { - return transform_images(a, b, [display](vec4f a, vec4f b) -> vec4f { - auto diff = abs(a - b); - if (display) { - auto d = max(diff); - return {d, d, d, 1}; - } else { - return diff; - } - }); -} - -image_t resize_image(const image_t& img, vec2i resize) { - auto size = img.size(); - if (resize.x == 0 && resize.y == 0) { - throw std::invalid_argument{"bad image size in resize"}; - } - if (resize.y == 0) { - resize.y = (int)round(resize.x * (double)size.y / (double)size.x); - } else if (resize.x == 0) { - resize.x = (int)round(resize.y * (double)size.x / (double)size.y); - } - auto res = image_t{resize}; - stbir_resize_float_linear((float*)img.data(), size.x, size.y, - sizeof(vec4f) * size.x, (float*)res.data(), resize.x, resize.y, - sizeof(vec4f) * resize.x, STBIR_RGBA); - return res; -} -image_t resize_image(const image_t& img, vec2i resize) { - auto size = img.size(); - if (resize.x == 0 && resize.y == 0) { - throw std::invalid_argument{"bad image size in resize"}; - } - if (resize.y == 0) { - resize.y = (int)round(resize.x * (double)size.y / (double)size.x); - } else if (resize.x == 0) { - resize.x = (int)round(resize.y * (double)size.x / (double)size.y); - } - auto res = image_t{resize}; - stbir_resize_uint8_linear((byte*)img.data(), size.x, size.y, - sizeof(vec4b) * size.x, (byte*)res.data(), resize.x, resize.y, - sizeof(vec4b) * resize.x, STBIR_RGBA); - return res; -} - -} // namespace yocto diff --git a/libs/yocto/yocto_image.h b/libs/yocto/yocto_image.h index a445e6874..496dfc4c6 100644 --- a/libs/yocto/yocto_image.h +++ b/libs/yocto/yocto_image.h @@ -311,45 +311,45 @@ inline T reconstruct_image(const image_t& img, vec2f uv, namespace yocto { // Conversion from/to floats. -image_t byte_to_float(const image_t& bt); -image_t float_to_byte(const image_t& fl); +inline image_t byte_to_float(const image_t& bt); +inline image_t float_to_byte(const image_t& fl); // Conversion between linear and gamma-encoded images. -image_t srgb_to_rgb(const image_t& srgb); -image_t rgb_to_srgb(const image_t& rgb); -image_t srgbb_to_rgb(const image_t& srgb); -image_t rgb_to_srgbb(const image_t& rgb); +inline image_t srgb_to_rgb(const image_t& srgb); +inline image_t rgb_to_srgb(const image_t& rgb); +inline image_t srgbb_to_rgb(const image_t& srgb); +inline image_t rgb_to_srgbb(const image_t& rgb); // Apply exposure and filmic tone mapping -image_t tonemap_image(const image_t& hdr, float exposure = 0, - bool filmic = false, bool srgb = true); -image_t tonemapb_image(const image_t& hdr, float exposure = 0, - bool filmic = false, bool srgb = true); +inline image_t tonemap_image(const image_t& hdr, + float exposure = 0, bool filmic = false, bool srgb = true); +inline image_t tonemapb_image(const image_t& hdr, + float exposure = 0, bool filmic = false, bool srgb = true); // fast tone map for UI -void tonemap_image(image_t& ldr, const image_t& hdr, +inline void tonemap_image(image_t& ldr, const image_t& hdr, float exposure = 0, bool filmic = false, bool srgb = true); // Apply exposure and filmic tone mapping -image_t colorgrade_image( +inline image_t colorgrade_image( const image_t& img, bool linear, const colorgrade_params& params); // compute white balance -vec3f compute_white_balance(const image_t& img); +inline vec3f compute_white_balance(const image_t& img); // fast color grade for UI -void colorgrade_image(image_t& graded, const image_t& img, +inline void colorgrade_image(image_t& graded, const image_t& img, bool linear, const colorgrade_params& params); // image compositing -image_t composite_image( +inline image_t composite_image( const image_t& foreground, const image_t& background); // removes alpha -image_t remove_alpha(const image_t& img); +inline image_t remove_alpha(const image_t& img); // turns alpha into a gray scale image -image_t alpha_to_gray(const image_t& img); +inline image_t alpha_to_gray(const image_t& img); // image difference -image_t image_difference( +inline image_t image_difference( const image_t& a, const image_t& b, bool display); // image resizing @@ -1238,6 +1238,108 @@ inline T reconstruct_curve(const vector& curve, float u, } // namespace yocto +// ----------------------------------------------------------------------------- +// IMPLEMENTATION OF IMAGE OPERATIONS +// ----------------------------------------------------------------------------- +namespace yocto { + +// Conversion from/to floats. +inline image_t byte_to_float(const image_t& bt) { + return transform_image(bt, [](vec4b a) { return byte_to_float(a); }); +} +inline image_t float_to_byte(const image_t& fl) { + return transform_image(fl, [](vec4f a) { return float_to_byte(a); }); +} + +// Conversion between linear and gamma-encoded images. +inline image_t srgb_to_rgb(const image_t& srgb) { + return transform_image(srgb, [](vec4f a) { return srgb_to_rgb(a); }); +} +inline image_t rgb_to_srgb(const image_t& rgb) { + return transform_image(rgb, [](vec4f a) { return rgb_to_srgb(a); }); +} +inline image_t srgbb_to_rgb(const image_t& srgb) { + return transform_image(srgb, [](vec4b a) { return srgbb_to_rgb(a); }); +} +inline image_t rgb_to_srgbb(const image_t& rgb) { + return transform_image(rgb, [](vec4f a) { return rgb_to_srgbb(a); }); +} + +// Apply exposure and filmic tone mapping +inline image_t tonemap_image( + const image_t& hdr, float exposure, bool filmic, bool srgb) { + return transform_image(hdr, [exposure, filmic, srgb](vec4f a) { + return tonemap(a, exposure, filmic, srgb); + }); +} +inline image_t tonemapb_image( + const image_t& hdr, float exposure, bool filmic, bool srgb) { + return transform_image(hdr, [exposure, filmic, srgb](vec4f a) { + return float_to_byte(tonemap(a, exposure, filmic, srgb)); + }); +} +inline void tonemap_image(image_t& ldr, const image_t& hdr, + float exposure, bool filmic, bool srgb) { + return transform_image(ldr, hdr, [exposure, filmic, srgb](vec4f a) { + return tonemap(a, exposure, filmic, srgb); + }); +} + +// Apply exposure and filmic tone mapping +inline image_t colorgrade_image( + const image_t& img, bool linear, const colorgrade_params& params) { + return transform_image( + img, [linear, params](vec4f a) { return colorgrade(a, linear, params); }); +} +inline void colorgrade_image(image_t& graded, const image_t& img, + bool linear, const colorgrade_params& params) { + return transform_image(graded, img, + [linear, params](vec4f a) { return colorgrade(a, linear, params); }); +} + +// compute white balance +inline vec3f compute_white_balance(const image_t& img) { + auto rgb = vec3f{0, 0, 0}; + for (auto& p : img) rgb += xyz(p); + if (rgb == vec3f{0, 0, 0}) return {0, 0, 0}; + return rgb / max(rgb); +} + +// image compositing +inline image_t composite_image( + const image_t& foreground, const image_t& background) { + return transform_images( + foreground, background, [](vec4f a, vec4f b) { return composite(a, b); }); +} + +// removes alpha +inline image_t remove_alpha(const image_t& img) { + return transform_image(img, [](vec4f a) -> vec4f { return {xyz(a), 1}; }); +} + +// turns alpha into a gray scale image +inline image_t alpha_to_gray(const image_t& img) { + return transform_image(img, [](vec4f a) -> vec4f { + auto g = a.w; + return {g, g, g, 1}; + }); +} + +inline image_t image_difference( + const image_t& a, const image_t& b, bool display) { + return transform_images(a, b, [display](vec4f a, vec4f b) -> vec4f { + auto diff = abs(a - b); + if (display) { + auto d = max(diff); + return {d, d, d, 1}; + } else { + return diff; + } + }); +} + +} // namespace yocto + #ifndef __CUDACC__ // ----------------------------------------------------------------------------- diff --git a/libs/yocto/yocto_scene.cpp b/libs/yocto/yocto_scene.cpp index fa19adb9f..36cfb36e5 100644 --- a/libs/yocto/yocto_scene.cpp +++ b/libs/yocto/yocto_scene.cpp @@ -28,6 +28,8 @@ #include "yocto_scene.h" +#include + #include #include #include @@ -131,6 +133,39 @@ texture_data image_to_texture(const image_t& image, bool linear) { return texture; } +image_t resize_image(const image_t& img, vec2i resize) { + auto size = img.size(); + if (resize.x == 0 && resize.y == 0) { + throw std::invalid_argument{"bad image size in resize"}; + } + if (resize.y == 0) { + resize.y = (int)round(resize.x * (double)size.y / (double)size.x); + } else if (resize.x == 0) { + resize.x = (int)round(resize.y * (double)size.x / (double)size.y); + } + auto res = image_t{resize}; + stbir_resize_float_linear((float*)img.data(), size.x, size.y, + sizeof(vec4f) * size.x, (float*)res.data(), resize.x, resize.y, + sizeof(vec4f) * resize.x, STBIR_RGBA); + return res; +} +image_t resize_image(const image_t& img, vec2i resize) { + auto size = img.size(); + if (resize.x == 0 && resize.y == 0) { + throw std::invalid_argument{"bad image size in resize"}; + } + if (resize.y == 0) { + resize.y = (int)round(resize.x * (double)size.y / (double)size.x); + } else if (resize.x == 0) { + resize.x = (int)round(resize.y * (double)size.x / (double)size.y); + } + auto res = image_t{resize}; + stbir_resize_uint8_linear((byte*)img.data(), size.x, size.y, + sizeof(vec4b) * size.x, (byte*)res.data(), resize.x, resize.y, + sizeof(vec4b) * resize.x, STBIR_RGBA); + return res; +} + } // namespace yocto // -----------------------------------------------------------------------------