6#include <Common/exceptions.h>
11#if PH_THIRD_PARTY_HAS_OPENEXR
14inline void copy_frame_to_imf_array(
17 Imf::Array2D<TImfPixel<T>>& array2D)
19 static_assert(std::is_same_v<T, half> || std::is_same_v<T, float>);
21 const auto dataWidth =
static_cast<long>(frame.widthPx());
22 const auto dataHeight =
static_cast<long>(frame.heightPx());
24 array2D.resizeErase(dataWidth, dataHeight);
26 [&array2D, alphaValue]
29 TImfPixel<T>& pixel = array2D[
static_cast<long>(y)][x];
31 pixel.r = framePixel[0];
32 pixel.g = framePixel[1];
33 pixel.b = framePixel[2];
38template<
typename T, std::
size_t N>
39inline void create_imf_header_for_frame(
41 const TFrame<T, N>& frame,
42 const std::array<std::string_view, N>& channelNames)
44 static_assert(std::is_same_v<T, half> || std::is_same_v<T, float>);
45 constexpr Imf::PixelType VALUE_TYPE = std::is_same_v<T, half> ? Imf::HALF : Imf::FLOAT;
57 header.lineOrder() = Imf::DECREASING_Y;
59 for(std::size_t channelIdx = 0; channelIdx < N; ++channelIdx)
62 if(channelNames[channelIdx].empty())
67 header.channels().insert(std::string(channelNames[channelIdx]), Imf::Channel(VALUE_TYPE));
71template<std::
size_t N>
72inline auto find_imf_channels(
73 const Imf::Header& header,
74 const std::array<std::string_view, N>& channelNames)
75-> std::array<const Imf::Channel*, N>
77 const Imf::ChannelList& channelList = header.channels();
79 std::array<const Imf::Channel*, N> channels;
80 for(std::size_t channelIdx = 0; channelIdx < N; ++channelIdx)
82 if(!channelNames[channelIdx].empty())
84 channels[channelIdx] = channelList.findChannel(std::string(channelNames[channelIdx]));
88 channels[channelIdx] =
nullptr;
95template<
typename T, std::
size_t N>
96inline void map_imf_framebuffer_to_frame(
97 Imf::FrameBuffer& framebuffer,
98 const Imf::Header& header,
99 const TFrame<T, N>& frame,
100 const std::array<std::string_view, N>& channelNames)
102 static_assert(std::is_same_v<T, half> || std::is_same_v<T, float>);
103 constexpr Imf::PixelType VALUE_TYPE = std::is_same_v<T, half> ? Imf::HALF : Imf::FLOAT;
106 const Imath::Box2i dataWindow = header.dataWindow();
107 const auto dataWidth = dataWindow.max.x - dataWindow.min.x + 1;
108 const auto dataHeight = dataWindow.max.y - dataWindow.min.y + 1;
109 const auto minDataX = dataWindow.min.x;
110 const auto minDataY = dataWindow.min.y;
112 if(frame.widthPx() != dataWidth || frame.heightPx() != dataHeight)
114 throw_formatted<IllegalOperationException>(
115 "cannot map frame data to Imf::Header, dimension mismatch (frame size = {}, header data "
116 "window size: ({}, {}))", frame.getSizePx(), dataWidth, dataHeight);
128 const auto pixelBytes =
sizeof(T) * N;
129 const auto scanlineBytes = pixelBytes * dataWidth;
130 const auto xStride =
static_cast<std::ptrdiff_t
>(pixelBytes);
131 const auto yStride = -
static_cast<std::ptrdiff_t
>(scanlineBytes);
133 PH_ASSERT_GE(dataHeight, 1);
134 const char* byteData =
reinterpret_cast<const char*
>(frame.getPixelData().data());
135 const char* firstScanlineData = byteData + scanlineBytes * (dataHeight - 1);
136 const char* firstDisplayWindowScanlineData = firstScanlineData + (-minDataY * yStride - minDataX * xStride);
140 const char* scanlineDataEnd = firstScanlineData + yStride * (dataHeight - 1) + xStride * dataWidth;
141 const T* scanlineDataEndExpected = frame.getPixelData().data() + N * frame.widthPx();
142 PH_ASSERT(scanlineDataEnd ==
reinterpret_cast<const char*
>(scanlineDataEndExpected));
145 for(std::size_t channelIdx = 0; channelIdx < N; ++channelIdx)
148 if(channelNames[channelIdx].empty())
154 std::string(channelNames[channelIdx]),
159 const_cast<char*
>(firstDisplayWindowScanlineData +
sizeof(T) * channelIdx),
TPixelType< HdrComponent > PixelType
Definition TFrame.h:28
IO functions and helpers for processing EXR files.
The root for all renderer implementations.
Definition EEngineProject.h:6
TFrame< HdrComponent, 3 > HdrRgbFrame
Definition frame_fwd.h:17
float32 HdrComponent
Definition frame_fwd.h:14