LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
lsstGil.h
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-2016 AURA/LSST.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 /*
24  * Types and classes to interface lsst::afw::image to boost::gil
25  *
26  * Tell doxygen to (usually) ignore this file
27  */
29 
30 #include <cstdint>
31 
32 #if !defined(GIL_LSST_H)
33 #define GIL_LSST_H 1
34 /*
35  * Extend the gil types to provide non-scaling float/int32 images, type bits32[fs]_noscale
36  */
37 #include <type_traits>
38 
39 #include "boost/mpl/assert.hpp"
40 #include "boost/mpl/bool.hpp"
41 #include "boost/mpl/if.hpp"
42 
43 
44 #include "boost/gil.hpp"
45 
46 #ifndef BOOST_GIL_DEFINE_BASE_TYPEDEFS
47 // Boost >=1.72 redefines GIL_ -> BOOST_GIL
48 // Add these for compatibility
49 #define BOOST_GIL_DEFINE_BASE_TYPEDEFS GIL_DEFINE_BASE_TYPEDEFS
50 #define BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL GIL_DEFINE_ALL_TYPEDEFS_INTERNAL
51 #endif
52 
53 
54 namespace lsst {
55 namespace afw {
56 namespace image {
57 
59 //
60 /* We want to be able to call operator+= in the global namespace, but define it in lsst::afw::image.
61  * To make this possible, at least one of its arguments must be in lsst::afw::image, so we define
62  * this type to make the argument lookup ("Koenig Lookup") work smoothly
63  */
64 struct pair2I : public std::pair<int, int> {
65  explicit pair2I(int first, int second) : std::pair<int, int>(first, second) {}
66  pair2I(std::pair<int, int> pair) : std::pair<int, int>(pair) {}
67 };
68 
75 template <typename T>
76 boost::gil::memory_based_2d_locator<T>& operator+=(boost::gil::memory_based_2d_locator<T>& loc, pair2I off) {
77  return (loc += boost::gil::point2<std::ptrdiff_t>(off.first, off.second));
78 }
83 template <typename T>
84 boost::gil::memory_based_2d_locator<T>& operator-=(boost::gil::memory_based_2d_locator<T>& loc, pair2I off) {
85  return (loc -= boost::gil::point2<std::ptrdiff_t>(off.first, off.second));
86 }
87 } // namespace image
88 } // namespace afw
89 } // namespace lsst
90 
91 namespace boost {
92 namespace gil {
97 template <typename T>
98 memory_based_2d_locator<T>& operator+=(memory_based_2d_locator<T>& loc, std::pair<int, int> off) {
99  return (loc += point2<std::ptrdiff_t>(off.first, off.second));
100 }
105 template <typename T>
106 memory_based_2d_locator<T>& operator-=(memory_based_2d_locator<T>& loc, std::pair<int, int> off) {
107  return (loc -= point2<std::ptrdiff_t>(off.first, off.second));
108 }
109 
110 /*
111  * Define types that are pure (un)signed long, without scaling into [0, 1]
112  */
113 using bits64 = uint64_t;
114 using bits64s = int64_t;
115 
116 BOOST_GIL_DEFINE_BASE_TYPEDEFS(64, bits64, gray)
117 BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64, bits64, dev2n, devicen_t<2>, devicen_layout_t<2>)
118 BOOST_GIL_DEFINE_BASE_TYPEDEFS(64s, bits64s, gray)
119 BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64s, bits64s, dev2n, devicen_t<2>, devicen_layout_t<2>)
120 
121 /*
122  * Define a type that's a pure float, without scaling into [0, 1]
123  */
124 using bits32f_noscale = float;
125 
126 BOOST_GIL_DEFINE_BASE_TYPEDEFS(32f_noscale, bits32f_noscale, gray)
127 BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f_noscale, bits32f_noscale, dev2n, devicen_t<2>, devicen_layout_t<2>)
128 
129 template <>
130 struct channel_multiplier<bits32f_noscale>
131  : public std::binary_function<bits32f_noscale, bits32f_noscale, bits32f_noscale> {
132  bits32f_noscale operator()(bits32f_noscale a, bits32f_noscale b) const { return a * b; }
133 };
134 
135 /*
136  * Define a type that's a pure double, without scaling into [0, 1]
137  */
138 using bits64f_noscale = double;
139 
140 BOOST_GIL_DEFINE_BASE_TYPEDEFS(64f_noscale, bits64f_noscale, gray)
141 BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64f_noscale, bits64f_noscale, dev2n, devicen_t<2>, devicen_layout_t<2>)
142 
143 //
144 // Conversions that don't scale
145 //
146 template <typename DstChannelV>
147 struct channel_converter<bits32f_noscale, DstChannelV>
148  : public std::unary_function<bits32f_noscale, DstChannelV> {
149  DstChannelV operator()(bits32f_noscale x) const { return DstChannelV(x + 0.5f); }
150 };
151 
152 template <typename SrcChannelV>
153 struct channel_converter<SrcChannelV, bits32f_noscale>
154  : public std::unary_function<SrcChannelV, bits32f_noscale> {
155  bits32f_noscale operator()(SrcChannelV x) const { return bits32f_noscale(x); }
156 };
157 
158 template <typename DstChannelV>
159 struct channel_converter<bits64f_noscale, DstChannelV>
160  : public std::unary_function<bits64f_noscale, DstChannelV> {
161  DstChannelV operator()(bits64f_noscale x) const { return DstChannelV(x + 0.5f); }
162 };
163 
164 template <typename SrcChannelV>
165 struct channel_converter<SrcChannelV, bits64f_noscale>
166  : public std::unary_function<SrcChannelV, bits64f_noscale> {
167  bits64f_noscale operator()(SrcChannelV x) const { return bits64f_noscale(x); }
168 };
169 
170 //
171 // Totally specialised templates to resolve ambiguities
172 //
173 #define LSST_CONVERT_NOOP(T1, T2) \
174  template <> \
175  struct channel_converter<T1, T2> : public std::unary_function<T1, T2> { \
176  T2 operator()(T1 x) const { return static_cast<T2>(x); } \
177  }; \
178  \
179  template <> \
180  struct channel_converter<T2, T1> : public std::unary_function<T2, T1> { \
181  T1 operator()(T2 x) const { return static_cast<T1>(x); } \
182  }
183 
184 LSST_CONVERT_NOOP(bits32f_noscale, bits64f_noscale);
185 
186 LSST_CONVERT_NOOP(unsigned char, short);
187 LSST_CONVERT_NOOP(unsigned char, unsigned short);
188 LSST_CONVERT_NOOP(unsigned char, int);
189 LSST_CONVERT_NOOP(unsigned short, short);
190 LSST_CONVERT_NOOP(unsigned short, int);
191 LSST_CONVERT_NOOP(short, int);
192 
193 #undef LSST_CONVERT_NOOP
194 
196 //
197 // These are in the boost::gil namespace in order to permit Koenig lookup
198 //
199 #define LSST_BOOST_GIL_OP_EQUALS(TYPE, OP) \
200  template <typename T2> \
201  TYPE##_pixel_t& operator OP##=(TYPE##_pixel_t& lhs, T2 rhs) { \
202  return (lhs = lhs OP rhs); \
203  }
204 
205 #define LSST_BOOST_GIL_OP_EQUALS_ALL(PIXTYPE) \
206  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, +) \
207  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, -) \
208  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, *) \
209  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, /) \
210  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, &) \
211  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, |)
212 
213 LSST_BOOST_GIL_OP_EQUALS_ALL(gray8)
214 LSST_BOOST_GIL_OP_EQUALS_ALL(gray8s)
215 LSST_BOOST_GIL_OP_EQUALS_ALL(gray16)
216 LSST_BOOST_GIL_OP_EQUALS_ALL(gray16s)
217 LSST_BOOST_GIL_OP_EQUALS_ALL(gray32)
218 LSST_BOOST_GIL_OP_EQUALS_ALL(gray32s)
219 LSST_BOOST_GIL_OP_EQUALS_ALL(gray32f_noscale)
220 LSST_BOOST_GIL_OP_EQUALS_ALL(gray64)
221 LSST_BOOST_GIL_OP_EQUALS_ALL(gray64s)
222 LSST_BOOST_GIL_OP_EQUALS_ALL(gray64f_noscale)
223 
224 #undef LSST_BOOST_GIL_OP_EQUALS
225 #undef LSST_BOOST_GIL_OP_EQUALS_ALL
226 } // namespace gil
227 } // namespace boost
228 
229 namespace lsst {
230 namespace afw {
231 namespace image {
232 namespace detail {
233 //
234 // Map typenames to gil's types
235 //
236 
237 template <typename T, bool rescale = false>
238 struct types_traits {
239  BOOST_MPL_ASSERT_MSG(boost::mpl::bool_<false>::value, I_DO_NOT_KNOW_HOW_TO_MAP_THIS_TYPE_TO_A_GIL_TYPE,
240  ());
241 };
242 
243 template <>
244 struct types_traits<unsigned char, false> {
245  using image_t = boost::gil::gray8_image_t;
246  using view_t = boost::gil::gray8_view_t;
247  using const_view_t = boost::gil::gray8c_view_t;
248  using reference = boost::gil::channel_traits<char>::reference;
249  using const_reference = boost::gil::channel_traits<char>::const_reference;
250 };
251 
252 template <>
253 struct types_traits<short, false> {
254  using image_t = boost::gil::gray16s_image_t;
255  using view_t = boost::gil::gray16s_view_t;
256  using const_view_t = boost::gil::gray16sc_view_t;
257  using reference = boost::gil::channel_traits<short>::reference;
258  using const_reference = boost::gil::channel_traits<short>::const_reference;
259 };
260 
261 template <>
262 struct types_traits<unsigned short, false> {
263  using image_t = boost::gil::gray16_image_t;
264  using view_t = boost::gil::gray16_view_t;
265  using const_view_t = boost::gil::gray16c_view_t;
266  using reference = boost::gil::channel_traits<unsigned short>::reference;
267  using const_reference = boost::gil::channel_traits<unsigned short>::const_reference;
268 };
269 
270 template <>
271 struct types_traits<int, false> {
272  using image_t = boost::gil::gray32s_image_t;
273  using view_t = boost::gil::gray32s_view_t;
274  using const_view_t = boost::gil::gray32sc_view_t;
275  using reference = boost::gil::channel_traits<int>::reference;
276  using const_reference = boost::gil::channel_traits<int>::const_reference;
277 };
278 
279 template <>
280 struct types_traits<unsigned int, false> {
281  using image_t = boost::gil::gray32_image_t;
282  using view_t = boost::gil::gray32_view_t;
283  using const_view_t = boost::gil::gray32c_view_t;
284  using reference = boost::gil::channel_traits<int>::reference;
285  using const_reference = boost::gil::channel_traits<int>::const_reference;
286 };
287 
288 template <>
289 struct types_traits<float, false> {
290  using image_t = boost::gil::gray32f_noscale_image_t;
291  using view_t = boost::gil::gray32f_noscale_view_t;
292  using const_view_t = boost::gil::gray32f_noscalec_view_t;
293  using reference = boost::gil::channel_traits<float>::reference;
294  using const_reference = boost::gil::channel_traits<float>::const_reference;
295 };
296 
297 template <>
298 struct types_traits<long, false> {
299  using image_t = boost::gil::gray64s_image_t;
300  using view_t = boost::gil::gray64s_view_t;
301  using const_view_t = boost::gil::gray64sc_view_t;
302  using reference = boost::gil::channel_traits<long>::reference;
303  using const_reference = boost::gil::channel_traits<long>::const_reference;
304 };
305 
306 template <>
307 struct types_traits<unsigned long, false> {
308  using image_t = boost::gil::gray64_image_t;
309  using view_t = boost::gil::gray64_view_t;
310  using const_view_t = boost::gil::gray64c_view_t;
311  using reference = boost::gil::channel_traits<long>::reference;
312  using const_reference = boost::gil::channel_traits<long>::const_reference;
313 };
314 
315 namespace {
316 struct unknown {}; // two unused and unimplemented types
317 struct unknown_u {};
318 /*
319  * Return long long type (as type) if it's a synonym for std::int64_t
320  * We also need unsigned long long (as type_u), because "unsigned unknown" won't compile
321  */
322 struct CheckBoost64 {
323  using type = boost::mpl::if_<std::is_same<long long, std::int64_t>, long long, struct unknown>::type;
324  using type_u = boost::mpl::if_<std::is_same<long long, std::int64_t>, unsigned long long, struct unknown_u>::type;
325 };
326 } // namespace
327 
328 template <>
329 struct types_traits<CheckBoost64::type, false> {
330  using image_t = boost::gil::gray64s_image_t;
331  using view_t = boost::gil::gray64s_view_t;
332  using const_view_t = boost::gil::gray64sc_view_t;
333  using reference = boost::gil::channel_traits<long>::reference;
334  using const_reference = boost::gil::channel_traits<long>::const_reference;
335 };
336 
337 template <>
338 struct types_traits<CheckBoost64::type_u, false> {
339  using image_t = boost::gil::gray64_image_t;
340  using view_t = boost::gil::gray64_view_t;
341  using const_view_t = boost::gil::gray64c_view_t;
342  using reference = boost::gil::channel_traits<long>::reference;
343  using const_reference = boost::gil::channel_traits<long>::const_reference;
344 };
345 
346 template <>
347 struct types_traits<double, false> {
348  using image_t = boost::gil::gray64f_noscale_image_t;
349  using view_t = boost::gil::gray64f_noscale_view_t;
350  using const_view_t = boost::gil::gray64f_noscalec_view_t;
351  using reference = boost::gil::channel_traits<double>::reference;
352  using const_reference = boost::gil::channel_traits<double>::const_reference;
353 };
354 
355 template <typename T>
356 struct const_iterator_type {
358 };
359 
360 template <typename T>
361 struct const_locator_type { // should assert that T is a locator
362  using type = typename T::const_t;
363 };
364 
365 using difference_type = boost::gil::point2<std::ptrdiff_t>; // type used to advance locators
366 }
367 } // namespace image
368 } // namespace afw
369 } // namespace lsst
370 
371 namespace boost {
372 namespace gil {
373 
375 template <typename View1, typename View2, typename View3, typename ViewDest, typename F>
376 BOOST_FORCEINLINE F transform_pixels(const View1& src1, const View2& src2, const View3& src3,
377  const ViewDest& dst, F fun) {
378  for (std::ptrdiff_t y = 0; y < dst.height(); ++y) {
379  typename View1::x_iterator srcIt1 = src1.row_begin(y);
380  typename View2::x_iterator srcIt2 = src2.row_begin(y);
381  typename View3::x_iterator srcIt3 = src3.row_begin(y);
382  typename ViewDest::x_iterator dstIt = dst.row_begin(y);
383  for (std::ptrdiff_t x = 0; x < dst.width(); ++x) dstIt[x] = fun(srcIt1[x], srcIt2[x], srcIt3[x]);
384  }
385  return fun;
386 }
387 
389 template <typename View1, typename View2, typename View3, typename View4, typename ViewDest, typename F>
390 BOOST_FORCEINLINE F transform_pixels(const View1& src1, const View2& src2, const View3& src3, const View4& src4,
391  const ViewDest& dst, F fun) {
392  for (std::ptrdiff_t y = 0; y < dst.height(); ++y) {
393  typename View1::x_iterator srcIt1 = src1.row_begin(y);
394  typename View2::x_iterator srcIt2 = src2.row_begin(y);
395  typename View3::x_iterator srcIt3 = src3.row_begin(y);
396  typename View4::x_iterator srcIt4 = src4.row_begin(y);
397  typename ViewDest::x_iterator dstIt = dst.row_begin(y);
398  for (std::ptrdiff_t x = 0; x < dst.width(); ++x)
399  dstIt[x] = fun(srcIt1[x], srcIt2[x], srcIt3[x], srcIt4[x]);
400  }
401  return fun;
402 }
403 } // namespace gil
404 } // namespace boost
405 #endif
double x
table::Key< int > type
Definition: Detector.cc:163
int y
Definition: SpanSet.cc:48
table::Key< int > b
table::Key< int > a
Definition: Polygon.cc:24
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Image< LhsPixelT > & operator+=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Add lhs to Image rhs (i.e. pixel-by-pixel addition) where types are different.
Definition: Image.cc:657
Image< LhsPixelT > & operator-=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Subtract lhs from Image rhs (i.e. pixel-by-pixel subtraction) where types are different.
Definition: Image.cc:663
A base class for image defects.
STL namespace.