14#include <lagrange/image/RawInputImage.h>
15#include <lagrange/utils/warning.h>
22template <
typename Archive>
28 ar.object([&](
auto& ar) {
29 ar(
"width") & m_width;
30 ar(
"height") & m_height;
31 ar(
"row_byte_stride") & m_row_byte_stride;
32 ar(
"pixel_precision") & m_pixel_precision;
33 ar(
"color_space") & m_color_space;
34 ar(
"tex_format") & m_tex_format;
35 ar(
"wrap_u") & m_wrap_u;
36 ar(
"wrap_v") & m_wrap_v;
37 ar(
"storage_format") & m_storage_format;
42 using ArrayScalar = int32_t;
43 const bool padding_required = (0 != ((get_row_stride() * m_height) %
sizeof(ArrayScalar)));
44 const size_t aligned_image_size =
45 get_row_stride() * m_height /
sizeof(ArrayScalar) + (padding_required ? 1 : 0);
48 std::vector<unsigned char> buf(aligned_image_size *
sizeof(ArrayScalar));
49 ArrayScalar* data =
reinterpret_cast<ArrayScalar*
>(buf.data());
54 static_cast<const unsigned char*
>(get_pixel_data()) - get_pixel_data_offset(),
55 get_row_stride() * m_height,
60 ar(
"pixels").template array_of<ArrayScalar>(
65 [&](
size_t i,
auto& ar) { ar& data[i]; });
68 LA_IGNORE_SHADOW_WARNING_END
72 typename TexcoordScalar,
75 typename InternalScalar,
76 uint32_t InternalNumChannels>
78 const TexcoordScalar u,
79 const TexcoordScalar v,
80 const texture_filtering filtering)
const
82 using ReturnTraits = PixelTraits<Scalar, NumChannels>;
83 using ReturnPixel =
typename ReturnTraits::Pixel;
84 using InternalTraits = PixelTraits<InternalScalar, InternalNumChannels>;
85 using InternalPixel =
typename InternalTraits::Pixel;
87 ReturnPixel rtn = ReturnTraits::zero();
90 const TexcoordScalar _0 =
static_cast<TexcoordScalar
>(0);
91 const TexcoordScalar _1 =
static_cast<TexcoordScalar
>(1);
92 const TexcoordScalar _05 =
static_cast<TexcoordScalar
>(0.5);
96 std::is_same<TexcoordScalar, float>::value || std::is_same<TexcoordScalar, double>::value,
97 "RawInputImage::sample, texcoord must be float or double");
99 std::is_same<Scalar, unsigned char>::value || std::is_same<Scalar, Eigen::half>::value ||
100 std::is_same<Scalar, float>::value || std::is_same<Scalar, double>::value,
101 "RawInputImage::sample, unsupported Scalar");
103 0u < NumChannels && NumChannels <= (static_cast<uint32_t>(texture_format::max) >> 8u),
104 "RawInputImage::sample, unsupported NumChannels");
106 std::is_same<InternalScalar, unsigned char>::value ||
107 std::is_same<InternalScalar, Eigen::half>::value ||
108 std::is_same<InternalScalar, float>::value ||
109 std::is_same<InternalScalar, double>::value,
110 "RawInputImage::sample, unsupported InternalScalar");
112 0u < InternalNumChannels &&
113 InternalNumChannels <= (static_cast<uint32_t>(texture_format::max) >> 8u),
114 "RawInputImage::sample, unsupported InternalNumChannels");
117 if (
sizeof(InternalScalar) != get_size_precision()) {
118 throw std::runtime_error(
"RawInputImage::sample, INTERNAL_PRECISION is incorrect!");
120 if (InternalNumChannels != get_num_channels()) {
121 throw std::runtime_error(
"RawInputImage::sample, InternalNumChannels is incorrect!");
125 if (std::is_same<Scalar, Eigen::half>::value ||
126 std::is_same<InternalScalar, Eigen::half>::value) {
127 throw std::runtime_error(
"RawInputImage::sample, half is not implemented yet!");
130 throw std::runtime_error(
"RawInputImage::sample, sRGB is not implemented yet!");
134 auto wrap = [_0, _1](
const TexcoordScalar c,
const wrap_mode m) -> TexcoordScalar {
135 if (_0 <= c && c <= _1) {
138 return c - std::floor(c);
140 return std::clamp(c, _0, _1);
142 const auto f = std::floor(c);
143 if (
static_cast<int>(f) & 1) {
149 throw std::runtime_error(
"unknown wrap_mode!");
153 auto _u = wrap(u, m_wrap_u);
154 auto _v = wrap(v, m_wrap_v);
155 assert(_0 <= _u && _u <= _1);
156 assert(_0 <= _v && _v <= _1);
164 const auto size_pixel = get_size_pixel();
165 const auto row_stride = get_row_stride();
166 const auto ptr =
static_cast<const unsigned char*
>(get_pixel_data()) - get_pixel_data_offset();
167 auto get_pixel = [&](
size_t x,
size_t y) -> InternalPixel {
168 assert(x < m_width && y < m_height);
169 return *
reinterpret_cast<const InternalPixel*
>(ptr + x * size_pixel + y * row_stride);
173 const auto x_coord = _u *
static_cast<TexcoordScalar
>(m_width);
174 const auto y_coord = _v *
static_cast<TexcoordScalar
>(m_height);
175 const auto min_num_channels = std::min(NumChannels, InternalNumChannels);
177 const auto x = std::clamp(
178 static_cast<size_t>(x_coord),
179 static_cast<size_t>(0),
180 static_cast<size_t>(m_width - 1));
181 const auto y = std::clamp(
182 static_cast<size_t>(y_coord),
183 static_cast<size_t>(0),
184 static_cast<size_t>(m_height - 1));
185 const auto pix = get_pixel(x, y);
186 for (uint32_t i = 0; i < min_num_channels; ++i) {
187 ReturnTraits::coeff(rtn, i) =
static_cast<Scalar
>(InternalTraits::coeff(pix, i));
190 auto sample_coord = [=](
const TexcoordScalar coord,
const size_t size,
const wrap_mode wrap_)
191 -> std::tuple<size_t, size_t, TexcoordScalar> {
192 assert(_0 <= coord && coord <=
static_cast<TexcoordScalar
>(size));
193 size_t coord0, coord1;
199 }
else if (coord + _05 >=
static_cast<TexcoordScalar
>(size)) {
202 t = coord - (
static_cast<TexcoordScalar
>(coord0) + _05);
205 coord0 = std::min(size - 2,
static_cast<size_t>(coord - _05));
207 t = coord - (
static_cast<TexcoordScalar
>(coord0) + _05);
209 return std::make_tuple(coord0, coord1, t);
211 const auto sample_x = sample_coord(x_coord, m_width, m_wrap_u);
212 const auto sample_y = sample_coord(y_coord, m_height, m_wrap_v);
213 InternalPixel pix[4] = {
214 get_pixel(std::get<0>(sample_x), std::get<0>(sample_y)),
215 get_pixel(std::get<1>(sample_x), std::get<0>(sample_y)),
216 get_pixel(std::get<0>(sample_x), std::get<1>(sample_y)),
217 get_pixel(std::get<1>(sample_x), std::get<1>(sample_y))};
218 TexcoordScalar weight[4] = {
219 (_1 - std::get<2>(sample_x)) * (_1 - std::get<2>(sample_y)),
220 std::get<2>(sample_x) * (_1 - std::get<2>(sample_y)),
221 (_1 - std::get<2>(sample_x)) * std::get<2>(sample_y),
222 std::get<2>(sample_x) * std::get<2>(sample_y)};
223 for (uint32_t i = 0; i < min_num_channels; ++i) {
224 TexcoordScalar sum = _0;
225 for (
int j = 0; j < 4; ++j) {
226 sum +=
static_cast<TexcoordScalar
>(InternalTraits::coeff(pix[j], i)) * weight[j];
228 ReturnTraits::coeff(rtn, i) =
static_cast<Scalar
>(sum);
231 throw std::runtime_error(
"RawInputImage::sample, unknown filtering type!");
237template <
typename TexcoordScalar,
typename Scalar, u
int32_t NumChannels>
239 const TexcoordScalar u,
240 const TexcoordScalar v,
244 using ReturnPixel =
typename ReturnTraits::Pixel;
246 ReturnPixel rtn = ReturnTraits::zero();
250 4u == (
static_cast<uint32_t
>(texture_format::max) >> 8u),
251 "the max channels are not 4 any more, need to update the following code");
253 const auto channels = get_num_channels();
255#define LA_RAWINPUTIMAGE_SAMPLE_IMPL(P, C, V) \
256 if (P == m_pixel_precision && C == channels) { \
257 return sample<TexcoordScalar, Scalar, NumChannels, V, C>(u, v, filtering); \
280#undef LA_RAWINPUTIMAGE_SAMPLE_IMPL
281 throw std::runtime_error(
282 "RawInputImage::sample, cannot deduce InternalScalar or InternalNumChannels!");
286template <
typename TexcoordScalar,
typename Scalar, u
int32_t NumChannels>
288 const TexcoordScalar u,
289 const TexcoordScalar v,
292 static_assert(std::is_floating_point_v<Scalar>,
"Pixel scalar type must be floating point");
294 auto pixel = sample<TexcoordScalar, Scalar, NumChannels>(u, v, filtering);
#define LA_IGNORE_SHADOW_WARNING_BEGIN
Ignore shadow warnings.
Definition: warning.h:68
Main namespace for Lagrange.
Definition: AABBIGL.h:30