Lagrange
ImageType.h
1/*
2 * Copyright 2023 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <Eigen/Eigen>
15
16#include <algorithm>
17#include <type_traits>
18
19namespace lagrange {
20namespace image {
21
22enum class ImagePrecision : unsigned int {
23 uint8,
24 int8,
25 uint32,
26 int32,
27 float32,
28 float64,
29 float16,
30 unknown,
31};
32enum class ImageChannel : unsigned int {
33 one = 1,
34 three = 3,
35 four = 4,
36 unknown,
37};
38
39template <typename T>
40struct ImageTraits;
41
42// to convert the value of image, included in ImagePrecision,
43// it is not the same as static_cast:
44// * unsigned char <==> float/double : [0, 255] <==> [-1.0, 1.0]
45// * others : clamp to avoid overflow
46template <typename VALUE_SRC, typename VALUE_DST>
47inline VALUE_DST convert_channel_value(VALUE_SRC val);
48
49template <typename PIX_SRC, typename PIX_DST>
51{
52 void operator()(const PIX_SRC& src, PIX_DST& dst) const;
53};
54
55
56template <typename TYPE>
58{
59 static constexpr ImagePrecision precision = ImagePrecision::unknown;
60 static constexpr ImageChannel channel = ImageChannel::unknown;
61};
62
63#ifdef LAGRANGE_IMAGE_TRAITS
64static_assert(false, "LAGRANGE_IMAGE_TRAITS was defined somewhere else")
65#elif LAGRANGE_IMAGE_COMMA
66static_assert(false, "LAGRANGE_IMAGE_COMMA was defined somewhere else")
67#else
68
69#define LAGRANGE_IMAGE_TRAITS(TYPE, VALUE, SIZE_OF_VALUE, PRECISION, CHANNEL) \
70 template <> \
71 struct ImageTraits<TYPE> \
72 { \
73 typedef VALUE TValue; \
74 static constexpr size_t value_size = SIZE_OF_VALUE; \
75 static constexpr ImagePrecision precision = ImagePrecision::PRECISION; \
76 static constexpr ImageChannel channel = ImageChannel::CHANNEL; \
77 };
78
79#define LAGRANGE_IMAGE_COMMA ,
80LAGRANGE_IMAGE_TRAITS(unsigned char, unsigned char, 1, uint8, one)
81LAGRANGE_IMAGE_TRAITS(
82 Eigen::Matrix<unsigned char LAGRANGE_IMAGE_COMMA 3 LAGRANGE_IMAGE_COMMA 1>,
83 unsigned char,
84 3,
85 uint8,
86 three)
87LAGRANGE_IMAGE_TRAITS(
88 Eigen::Matrix<unsigned char LAGRANGE_IMAGE_COMMA 4 LAGRANGE_IMAGE_COMMA 1>,
89 unsigned char,
90 4,
91 uint8,
92 four)
93LAGRANGE_IMAGE_TRAITS(char, char, 1, int8, one)
94LAGRANGE_IMAGE_TRAITS(
95 Eigen::Matrix<char LAGRANGE_IMAGE_COMMA 3 LAGRANGE_IMAGE_COMMA 1>,
96 char,
97 3,
98 int8,
99 three)
100LAGRANGE_IMAGE_TRAITS(
101 Eigen::Matrix<char LAGRANGE_IMAGE_COMMA 4 LAGRANGE_IMAGE_COMMA 1>,
102 char,
103 4,
104 int8,
105 four)
106LAGRANGE_IMAGE_TRAITS(unsigned int, unsigned int, 1, uint32, one)
107LAGRANGE_IMAGE_TRAITS(
108 Eigen::Matrix<unsigned int LAGRANGE_IMAGE_COMMA 3 LAGRANGE_IMAGE_COMMA 1>,
109 unsigned int,
110 3,
111 uint32,
112 three)
113LAGRANGE_IMAGE_TRAITS(
114 Eigen::Matrix<unsigned int LAGRANGE_IMAGE_COMMA 4 LAGRANGE_IMAGE_COMMA 1>,
115 unsigned int,
116 4,
117 uint32,
118 four)
119LAGRANGE_IMAGE_TRAITS(int, int, 1, int32, one)
120LAGRANGE_IMAGE_TRAITS(Eigen::Vector3i, int, 3, int32, three)
121LAGRANGE_IMAGE_TRAITS(Eigen::Vector4i, int, 4, int32, four)
122LAGRANGE_IMAGE_TRAITS(float, float, 1, float32, one)
123LAGRANGE_IMAGE_TRAITS(Eigen::Vector3f, float, 3, float32, three)
124LAGRANGE_IMAGE_TRAITS(Eigen::Vector4f, float, 4, float32, four)
125LAGRANGE_IMAGE_TRAITS(double, double, 1, float64, one)
126LAGRANGE_IMAGE_TRAITS(Eigen::Vector3d, double, 3, float64, three)
127LAGRANGE_IMAGE_TRAITS(Eigen::Vector4d, double, 4, float64, four)
128LAGRANGE_IMAGE_TRAITS(Eigen::half, Eigen::half, 1, float16, one)
129LAGRANGE_IMAGE_TRAITS(
130 Eigen::Matrix<Eigen::half LAGRANGE_IMAGE_COMMA 3 LAGRANGE_IMAGE_COMMA 1>,
131 Eigen::half,
132 3,
133 float16,
134 three)
135LAGRANGE_IMAGE_TRAITS(
136 Eigen::Matrix<Eigen::half LAGRANGE_IMAGE_COMMA 4 LAGRANGE_IMAGE_COMMA 1>,
137 Eigen::half,
138 4,
139 float16,
140 four)
141
142#undef LAGRANGE_IMAGE_TRAITS
143#undef LAGRANGE_IMAGE_COMMA
144#endif
145
146 template <typename VALUE_SRC, typename VALUE_DST>
147 inline VALUE_DST convert_channel_value(VALUE_SRC val)
148{
149 // convert between same type
150 if constexpr (std::is_same<VALUE_SRC, VALUE_DST>::value) {
151 return val;
152 }
153 // convert from unsigned char and float/double
154 else if constexpr (
155 std::is_same<VALUE_SRC, unsigned char>::value && std::is_floating_point<VALUE_DST>::value) {
156 return static_cast<VALUE_DST>(val) /
157 static_cast<VALUE_DST>(std::numeric_limits<unsigned char>::max());
158 }
159 // convert from float/double to unsigned char
160 else if constexpr (
161 std::is_floating_point<VALUE_SRC>::value && std::is_same<VALUE_DST, unsigned char>::value) {
162 return static_cast<unsigned char>(
163 std::clamp(val, static_cast<VALUE_SRC>(0), static_cast<VALUE_SRC>(1)) *
164 static_cast<VALUE_SRC>(std::numeric_limits<unsigned char>::max()));
165 } else {
166 // clamping, prepare to convert from signed to unsigned
167 if constexpr (std::is_signed<VALUE_SRC>::value && !std::is_signed<VALUE_DST>::value) {
168 val = std::max(val, static_cast<VALUE_SRC>(0));
169 }
170 // convert between integral types, and it may overflow
171 if constexpr (
172 (std::is_integral<VALUE_SRC>::value && std::is_integral<VALUE_DST>::value) &&
173 (sizeof(VALUE_SRC) > sizeof(VALUE_DST) ||
174 (sizeof(VALUE_SRC) == sizeof(VALUE_DST) && std::is_signed<VALUE_DST>::value))) {
175 return static_cast<VALUE_DST>(
176 std::min(val, static_cast<VALUE_SRC>(std::numeric_limits<VALUE_DST>::max())));
177 }
178 // the rest
179 else {
180 return static_cast<VALUE_DST>(val);
181 }
182 }
183}
184
185template <typename PIX_SRC, typename PIX_DST>
186inline void convert_image_pixel<PIX_SRC, PIX_DST>::operator()(const PIX_SRC& src, PIX_DST& dst)
187 const
188{
189 using V_SRC = typename ImageTraits<PIX_SRC>::TValue;
190 using V_DST = typename ImageTraits<PIX_DST>::TValue;
191 constexpr size_t L_SRC = static_cast<size_t>(ImageTraits<PIX_SRC>::channel);
192 constexpr size_t L_DST = static_cast<size_t>(ImageTraits<PIX_DST>::channel);
193 // convert [1] to [1]
194 if constexpr (1 == L_SRC && 1 == L_DST) {
195 dst = convert_channel_value<V_SRC, V_DST>(src);
196 }
197 // convert [1] to [n]
198 else if constexpr (1 == L_SRC) {
199 dst(0) = convert_channel_value<V_SRC, V_DST>(src);
200 for (size_t i = 1; i < L_DST; ++i) {
201 dst(i) = static_cast<V_DST>(0);
202 }
203 if constexpr (3 <= L_DST) {
204 dst(1) = dst(0);
205 dst(2) = dst(0);
206 }
207 if constexpr (4 == L_DST) {
208 if constexpr (std::is_floating_point<V_DST>::value) {
209 dst(3) = static_cast<V_DST>(1);
210 } else if constexpr (!std::is_signed<V_DST>::value && 1 == sizeof(V_DST)) {
211 dst(3) = std::numeric_limits<V_DST>::max();
212 } else {
213 dst(3) = static_cast<V_DST>(0);
214 }
215 }
216 }
217 // convert [n] to [1]
218 else if constexpr (1 == L_DST) {
219 dst = convert_channel_value<V_SRC, V_DST>(src(0));
220 }
221 // convert [m] to [n]
222 else {
223 constexpr size_t L_MIN = std::min(L_SRC, L_DST);
224 for (size_t i = 0; i < L_MIN; ++i) {
225 dst(i) = convert_channel_value<V_SRC, V_DST>(src(i));
226 }
227 if constexpr (3 == L_MIN && 4 == L_DST) {
228 if constexpr (std::is_floating_point<V_DST>::value) {
229 dst(3) = static_cast<V_DST>(1);
230 } else if constexpr (!std::is_signed<V_DST>::value && 1 == sizeof(V_DST)) {
231 dst(3) = std::numeric_limits<V_DST>::max();
232 } else {
233 dst(3) = static_cast<V_DST>(0);
234 }
235 } else {
236 for (size_t i = L_MIN; i < L_DST; ++i) {
237 dst(i) = static_cast<V_DST>(0);
238 }
239 }
240 }
241}
242} // namespace image
243} // namespace lagrange
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Definition: ImageType.h:58
Definition: ImageType.h:51