14#include <lagrange/Logger.h>
15#include <lagrange/image/Array3D.h>
16#include <lagrange/image/View3D.h>
17#include <lagrange/image_io/exr.h>
18#include <lagrange/image_io/load_image.h>
19#include <lagrange/scene/Scene.h>
20#include <lagrange/utils/assert.h>
24using Array3Df = lagrange::image::experimental::Array3D<float>;
25using View3Df = lagrange::image::experimental::View3D<float>;
26using ConstView3Df = lagrange::image::experimental::View3D<const float>;
28template <
size_t NumChannels,
typename Precision>
31 size_t width = img.width;
32 size_t height = img.height;
37 std::conditional_t<NumChannels == 1, Precision, Eigen::Vector<Precision, NumChannels>>;
39 std::conditional_t<NumChannels == 1, float, Eigen::Vector<float, NumChannels>>;
43 img.storage->get_full_size()(0) /
sizeof(SourcePixel),
44 img.storage->get_full_size()(1),
53 for (
size_t x = 0; x < width; ++x) {
54 for (
size_t y = 0; y < height; ++y) {
55 auto pixel = target_view(x, y);
56 if constexpr (NumChannels == 1) {
57 result(x, y, 0) = pixel;
59 for (
size_t c = 0; c < NumChannels; ++c) {
60 result(x, y, c) = pixel[c];
69template <
size_t NumChannels>
72 switch (img.precision) {
73 case lagrange::image::ImagePrecision::float32:
return convert_from<NumChannels, float>(img);
74 case lagrange::image::ImagePrecision::float64:
return convert_from<NumChannels, double>(img);
75 case lagrange::image::ImagePrecision::uint8:
76 return convert_from<NumChannels, unsigned char>(img);
77 case lagrange::image::ImagePrecision::int8:
return convert_from<NumChannels, char>(img);
78 case lagrange::image::ImagePrecision::uint32:
return convert_from<NumChannels, uint32_t>(img);
79 case lagrange::image::ImagePrecision::int32:
return convert_from<NumChannels, int32_t>(img);
80 case lagrange::image::ImagePrecision::float16:
81 return convert_from<NumChannels, Eigen::half>(img);
82 default:
throw std::runtime_error(
"Unsupported precision");
86inline Array3Df load_image(
const lagrange::fs::path& path)
88 auto img = lagrange::image_io::load_image(path);
90 switch (img.channel) {
91 case lagrange::image::ImageChannel::one:
return convert_from<1>(img);
92 case lagrange::image::ImageChannel::three:
return convert_from<3>(img);
93 case lagrange::image::ImageChannel::four:
return convert_from<4>(img);
94 default:
throw std::runtime_error(
"Unsupported number of channels");
98inline void save_image(lagrange::fs::path path, View3Df image)
100 if (path.extension() !=
".exr") {
101 lagrange::logger().warn(
"Only .exr output files are supported. Saving as .exr.");
102 path = path.replace_extension(
".exr");
107 const size_t width =
image.extent(0);
108 const size_t height =
image.extent(1);
109 const size_t num_channels =
image.extent(2);
111 std::vector<float> scanline(width * height * num_channels);
112 for (
size_t x = 0; x < width; ++x) {
113 for (
size_t y = 0; y < height; ++y) {
114 for (
size_t c = 0; c < num_channels; ++c) {
115 scanline[y * width * num_channels + x * num_channels + c] =
image(x, y, c);
120 lagrange::image_io::save_image_exr(
122 static_cast<const void*
>(scanline.data()),
123 static_cast<int>(width),
124 static_cast<int>(height),
125 static_cast<int>(num_channels),
126 lagrange::image_io::TinyexrPixelType::float32);
129inline void sort_paths(std::vector<lagrange::fs::path>& paths)
131 auto original = paths;
132 std::sort(paths.begin(), paths.end());
133 if (!std::is_sorted(original.begin(), original.end())) {
134 lagrange::logger().warn(
"Input filenames were not sorted. Using sorted order.");
Definition ImageView.h:56
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
Array3D< T > create_image(size_t width, size_t height, size_t num_channels)
Create an image with the given dimensions and number of channels.
Definition Array3D.h:46
Basic image data structure.
Definition load_image.h:28