Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
PictureData.ipp
Go to the documentation of this file.
1#include "Frame/PictureData.h"
2#include "Frame/TFrame.h"
3
4#include <Common/assertion.h>
5#include <Common/utility.h>
6
7#include <algorithm>
8#include <type_traits>
9#include <utility>
10
11namespace ph
12{
13
15 : m_sizePx(0)
16 , m_numComponents(0)
17 , m_componentType(EPicturePixelComponent::Empty)
18 , m_data(nullptr)
19 , m_numBytesInData(0)
20{}
21
23 const math::Vector2S sizePx,
24 const std::size_t numPicComponents,
25 const EPicturePixelComponent componentType)
26
27 : m_sizePx(sizePx)
28 , m_numComponents(numPicComponents)
29 , m_componentType(componentType)
30 , m_data()
31 , m_numBytesInData(0)
32{
33 m_numBytesInData = sizePx.product() * numPicComponents * num_bytes_in_component(componentType);
34 m_data = std::make_unique<std::byte[]>(m_numBytesInData);
35}
36
37template<typename PixelData>
39 const math::Vector2S sizePx,
40 const std::size_t numPicComponents,
41 const EPicturePixelComponent componentType,
42 const PixelData* const pixelData,
43 const std::size_t pixelDataSize)
44
46 sizePx,
47 numPicComponents,
48 componentType)
49{
50 setPixels(pixelData, pixelDataSize);
51}
52
54 : PictureData()
55{
56 *this = std::move(other);
57}
58
60{
61 return m_sizePx;
62}
63
64inline std::size_t PictureData::getWidthPx() const
65{
66 return getSizePx().x();
67}
68
69inline std::size_t PictureData::getHeightPx() const
70{
71 return getSizePx().y();
72}
73
74inline std::size_t PictureData::numComponents() const
75{
76 return m_numComponents;
77}
78
80{
81 return m_componentType;
82}
83
85{
86 return {m_data.get(), m_numBytesInData};
87}
88
90{
91 return {m_data.get(), m_numBytesInData};
92}
93
94template<typename PixelData>
96 const PixelData* const pixelData,
97 const std::size_t numPixelDataElements)
98{
99 // Note that the following assertion my not be true:
100 //
101 // `PH_ASSERT_EQ(m_numBytesInData, sizePx.product() * inNumComponents * sizeof(PixelData));`
102 //
103 // Consider a typical case where RGBA is packed into an `int32`. `PixelData` would be `int32`
104 // which contains 4 components already. It is up to the user to provide suitably-sized `pixelData`.
105
106 // Implies that `PixelData` should not be padded
107 PH_ASSERT_EQ(m_numBytesInData, numPixelDataElements * sizeof(PixelData));
108
109 // Should have been allocated; set pixels on empty picture is not allowed.
110 PH_ASSERT(m_data);
111
112 // Generally we would want `PixelData` to be trivially copyable since we are basically handling
113 // raw bytes here
114 static_assert(std::is_trivially_copyable_v<PixelData>);
115
116 std::copy(
117 reinterpret_cast<const std::byte*>(pixelData),
118 reinterpret_cast<const std::byte*>(pixelData + numPixelDataElements),
119 m_data.get());
120}
121
122template<typename FrameComponent, std::size_t N>
124{
125 switch(m_componentType)
126 {
128 return pictureToFrame<int8, FrameComponent, N>();
129
131 return pictureToFrame<uint8, FrameComponent, N>();
132
134 return pictureToFrame<int16, FrameComponent, N>();
135
137 return pictureToFrame<uint16, FrameComponent, N>();
138
140 return pictureToFrame<int32, FrameComponent, N>();
141
143 return pictureToFrame<uint32, FrameComponent, N>();
144
146 return pictureToFrame<int64, FrameComponent, N>();
147
149 return pictureToFrame<uint64, FrameComponent, N>();
150
152 return pictureToFrame<float32, FrameComponent, N>();
153
155 return pictureToFrame<float64, FrameComponent, N>();
156
157 default:
158 PH_ASSERT_UNREACHABLE_SECTION();
159 break;
160 }
161
163}
164
165inline bool PictureData::isEmpty() const
166{
167 return m_data == nullptr;
168}
169
171{
172 m_sizePx = rhs.m_sizePx;
173 m_numComponents = rhs.m_numComponents;
174 m_componentType = rhs.m_componentType;
175 m_data = std::move(rhs.m_data);
176 m_numBytesInData = rhs.m_numBytesInData;
177
178 return *this;
179}
180
181template<typename PictureComponent, typename FrameComponent, std::size_t N>
182inline TFrame<FrameComponent, N> PictureData::pictureToFrame() const
183{
184 // Generally we would want `PictureComponent` and `FrameComponent` to be trivially copyable since
185 // we are basically handling raw bytes here
186 static_assert(std::is_trivially_copyable_v<PictureComponent>);
187 static_assert(std::is_trivially_copyable_v<FrameComponent>);
188
189 PH_ASSERT(m_data);
190
191 using FrameType = TFrame<FrameComponent, N>;
192 using FramePixelType = typename FrameType::PixelType;
193
194 // Pixel component casting is based on the smaller number of components of the two--other
195 // components are either discarded or defaulted to 0.
196 const std::size_t minComponents = std::min(m_numComponents, N);
197
198 FrameType frame(
199 lossless_cast<uint32>(m_sizePx.x()),
200 lossless_cast<uint32>(m_sizePx.y()));
201 frame.forEachPixel(
202 [this, minComponents](const std::size_t x, const std::size_t y)
203 {
204 FramePixelType pixel;
205 for(std::size_t ci = 0; ci < minComponents; ++ci)
206 {
207 const std::size_t byteIndex = getByteIndex<PictureComponent>(x, y, ci);
208
209 PictureComponent pictureComponent;
210 std::copy(
211 m_data.get() + byteIndex,
212 m_data.get() + byteIndex + sizeof(PictureComponent),
213 reinterpret_cast<std::byte*>(&pictureComponent));
214
215 pixel[ci] = static_cast<FrameComponent>(pictureComponent);
216 }
217
218 return pixel;
219 });
220
221 return frame;
222}
223
224template<typename PictureComponent>
225inline std::size_t PictureData::getByteIndex(
226 const std::size_t xPx,
227 const std::size_t yPx,
228 const std::size_t componentIndex) const
229{
230 PH_ASSERT_LT(xPx, m_sizePx.x());
231 PH_ASSERT_LT(yPx, m_sizePx.y());
232 PH_ASSERT_LT(componentIndex, m_numComponents);
233
234 const auto linearPixelIndex = yPx * m_sizePx.x() + xPx;
235 return (linearPixelIndex * m_numComponents + componentIndex) * sizeof(PictureComponent);
236}
237
238}// end namespace ph
Definition PictureData.h:21
const math::Vector2S & getSizePx() const
Definition PictureData.ipp:59
PictureData & operator=(PictureData &&rhs)
Definition PictureData.ipp:170
PictureData()
Creates an empty picture.
Definition PictureData.ipp:14
std::size_t getHeightPx() const
Definition PictureData.ipp:69
TSpan< std::byte > getBytes()
Definition PictureData.ipp:84
EPicturePixelComponent getComponentType() const
Definition PictureData.ipp:79
std::size_t getWidthPx() const
Definition PictureData.ipp:64
bool isEmpty() const
Definition PictureData.ipp:165
void setPixels(const PixelData *pixelData, std::size_t numPixelDataElements)
Set pixel data directly. This method also supports packed pixel data. For example,...
Definition PictureData.ipp:95
TFrame< FrameComponent, N > toFrame() const
Definition PictureData.ipp:123
std::size_t numComponents() const
Definition PictureData.ipp:74
Definition TFrame.h:21
T & x()
Definition TVector2.ipp:38
T & y()
Definition TVector2.ipp:44
T product() const
Definition TArithmeticArrayBase.ipp:358
The root for all renderer implementations.
Definition EEngineProject.h:6
std::span< const T, EXTENT > TSpanView
Same as TSpan, except that the objects are const-qualified. Note that for pointer types,...
Definition TSpan.h:19
EPicturePixelComponent
Definition picture_basics.h:11
std::span< T, EXTENT > TSpan
A contiguous sequence of objects of type T. Effectively the same as std::span.
Definition TSpan.h:12
std::size_t num_bytes_in_component(const EPicturePixelComponent componentType)
Definition picture_basics.h:27