LSSTApplications  20.0.0
LSSTDataManagementBasePackage
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 //#define BOOST_GIL_USE_CONCEPT_CHECK 1
44 
45 #if defined(__ICC)
46 #pragma warning(push)
47 #pragma warning(disable : 68)
48 #pragma warning(disable : 304)
49 #endif
50 
51 #include "boost/version.hpp"
52 #if BOOST_VERSION < 106900
53 #include "boost/gil/gil_all.hpp"
54 #else
55 #include "boost/gil.hpp"
56 #endif
57 
58 #if defined(__ICC)
59 #pragma warning(pop)
60 #endif
61 
62 namespace lsst {
63 namespace afw {
64 namespace image {
65 
67 //
68 /* We want to be able to call operator+= in the global namespace, but define it in lsst::afw::image.
69  * To make this possible, at least one of its arguments must be in lsst::afw::image, so we define
70  * this type to make the argument lookup ("Koenig Lookup") work smoothly
71  */
72 struct pair2I : public std::pair<int, int> {
73  explicit pair2I(int first, int second) : std::pair<int, int>(first, second) {}
74  pair2I(std::pair<int, int> pair) : std::pair<int, int>(pair) {}
75 };
76 
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 }
91 template <typename T>
92 boost::gil::memory_based_2d_locator<T>& operator-=(boost::gil::memory_based_2d_locator<T>& loc, pair2I off) {
93  return (loc -= boost::gil::point2<std::ptrdiff_t>(off.first, off.second));
94 }
95 } // namespace image
96 } // namespace afw
97 } // namespace lsst
98 
99 namespace boost {
100 namespace gil {
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 }
113 template <typename T>
114 memory_based_2d_locator<T>& operator-=(memory_based_2d_locator<T>& loc, std::pair<int, int> off) {
115  return (loc -= point2<std::ptrdiff_t>(off.first, off.second));
116 }
117 
118 /*
119  * Define types that are pure (un)signed long, without scaling into [0, 1]
120  */
121 typedef uint64_t bits64;
122 typedef int64_t bits64s;
123 
124 GIL_DEFINE_BASE_TYPEDEFS(64, bits64, gray)
125 GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64, bits64, dev2n, devicen_t<2>, devicen_layout_t<2>)
126 GIL_DEFINE_BASE_TYPEDEFS(64s, bits64s, gray)
127 GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64s, bits64s, dev2n, devicen_t<2>, devicen_layout_t<2>)
128 
129 /*
130  * Define a type that's a pure float, without scaling into [0, 1]
131  */
132 typedef float bits32f_noscale;
133 
134 GIL_DEFINE_BASE_TYPEDEFS(32f_noscale, bits32f_noscale, gray)
135 GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f_noscale, bits32f_noscale, dev2n, devicen_t<2>, devicen_layout_t<2>)
136 
137 template <>
138 struct channel_multiplier<bits32f_noscale>
139  : public std::binary_function<bits32f_noscale, bits32f_noscale, bits32f_noscale> {
140  bits32f_noscale operator()(bits32f_noscale a, bits32f_noscale b) const { return a * b; }
141 };
142 
143 /*
144  * Define a type that's a pure double, without scaling into [0, 1]
145  */
146 typedef double bits64f_noscale;
147 
148 GIL_DEFINE_BASE_TYPEDEFS(64f_noscale, bits64f_noscale, gray)
149 GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64f_noscale, bits64f_noscale, dev2n, devicen_t<2>, devicen_layout_t<2>)
150 
151 //
152 // Conversions that don't scale
153 //
154 template <typename DstChannelV>
155 struct channel_converter<bits32f_noscale, DstChannelV>
156  : public std::unary_function<bits32f_noscale, DstChannelV> {
157  DstChannelV operator()(bits32f_noscale x) const { return DstChannelV(x + 0.5f); }
158 };
159 
160 template <typename SrcChannelV>
161 struct channel_converter<SrcChannelV, bits32f_noscale>
162  : public std::unary_function<SrcChannelV, bits32f_noscale> {
163  bits32f_noscale operator()(SrcChannelV x) const { return bits32f_noscale(x); }
164 };
165 
166 template <typename DstChannelV>
167 struct channel_converter<bits64f_noscale, DstChannelV>
168  : public std::unary_function<bits64f_noscale, DstChannelV> {
169  DstChannelV operator()(bits64f_noscale x) const { return DstChannelV(x + 0.5f); }
170 };
171 
172 template <typename SrcChannelV>
173 struct channel_converter<SrcChannelV, bits64f_noscale>
174  : public std::unary_function<SrcChannelV, bits64f_noscale> {
175  bits64f_noscale operator()(SrcChannelV x) const { return bits64f_noscale(x); }
176 };
177 
178 //
179 // Totally specialised templates to resolve ambiguities
180 //
181 #define LSST_CONVERT_NOOP(T1, T2) \
182  template <> \
183  struct channel_converter<T1, T2> : public std::unary_function<T1, T2> { \
184  T2 operator()(T1 x) const { return static_cast<T2>(x); } \
185  }; \
186  \
187  template <> \
188  struct channel_converter<T2, T1> : public std::unary_function<T2, T1> { \
189  T1 operator()(T2 x) const { return static_cast<T1>(x); } \
190  }
191 
192 LSST_CONVERT_NOOP(bits32f_noscale, bits64f_noscale);
193 
194 LSST_CONVERT_NOOP(unsigned char, short);
195 LSST_CONVERT_NOOP(unsigned char, unsigned short);
196 LSST_CONVERT_NOOP(unsigned char, int);
197 LSST_CONVERT_NOOP(unsigned short, short);
198 LSST_CONVERT_NOOP(unsigned short, int);
199 LSST_CONVERT_NOOP(short, int);
200 
201 #undef LSST_CONVERT_NOOP
202 
204 //
205 // These are in the boost::gil namespace in order to permit Koenig lookup
206 //
207 #define LSST_BOOST_GIL_OP_EQUALS(TYPE, OP) \
208  template <typename T2> \
209  TYPE##_pixel_t& operator OP##=(TYPE##_pixel_t& lhs, T2 rhs) { \
210  return (lhs = lhs OP rhs); \
211  }
212 
213 #define LSST_BOOST_GIL_OP_EQUALS_ALL(PIXTYPE) \
214  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, +) \
215  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, -) \
216  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, *) \
217  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, /) \
218  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, &) \
219  LSST_BOOST_GIL_OP_EQUALS(PIXTYPE, |)
220 
221 LSST_BOOST_GIL_OP_EQUALS_ALL(gray8)
222 LSST_BOOST_GIL_OP_EQUALS_ALL(gray8s)
223 LSST_BOOST_GIL_OP_EQUALS_ALL(gray16)
224 LSST_BOOST_GIL_OP_EQUALS_ALL(gray16s)
225 LSST_BOOST_GIL_OP_EQUALS_ALL(gray32)
226 LSST_BOOST_GIL_OP_EQUALS_ALL(gray32s)
227 LSST_BOOST_GIL_OP_EQUALS_ALL(gray32f_noscale)
228 LSST_BOOST_GIL_OP_EQUALS_ALL(gray64)
229 LSST_BOOST_GIL_OP_EQUALS_ALL(gray64s)
230 LSST_BOOST_GIL_OP_EQUALS_ALL(gray64f_noscale)
231 
232 #undef LSST_BOOST_GIL_OP_EQUALS
233 #undef LSST_BOOST_GIL_OP_EQUALS_ALL
234 } // namespace gil
235 } // namespace boost
236 
237 namespace lsst {
238 namespace afw {
239 namespace image {
240 namespace detail {
241 //
242 // Map typenames to gil's types
243 //
244 #if defined(__ICC)
245 #pragma warning(push)
246 #pragma warning(disable : 304)
247 #endif
248 
249 template <typename T, bool rescale = false>
250 struct types_traits {
251  BOOST_MPL_ASSERT_MSG(boost::mpl::bool_<false>::value, I_DO_NOT_KNOW_HOW_TO_MAP_THIS_TYPE_TO_A_GIL_TYPE,
252  ());
253 };
254 #if defined(__ICC)
255 #pragma warning(pop)
256 #endif
257 
258 template <>
259 struct types_traits<unsigned char, false> {
260  typedef boost::gil::gray8_image_t image_t;
261  typedef boost::gil::gray8_view_t view_t;
262  typedef boost::gil::gray8c_view_t const_view_t;
263  typedef boost::gil::channel_traits<char>::reference reference;
264  typedef boost::gil::channel_traits<char>::const_reference const_reference;
265 };
266 
267 template <>
268 struct types_traits<short, false> {
269  typedef boost::gil::gray16s_image_t image_t;
270  typedef boost::gil::gray16s_view_t view_t;
271  typedef boost::gil::gray16sc_view_t const_view_t;
272  typedef boost::gil::channel_traits<short>::reference reference;
273  typedef boost::gil::channel_traits<short>::const_reference const_reference;
274 };
275 
276 template <>
277 struct types_traits<unsigned short, false> {
278  typedef boost::gil::gray16_image_t image_t;
279  typedef boost::gil::gray16_view_t view_t;
280  typedef boost::gil::gray16c_view_t const_view_t;
281  typedef boost::gil::channel_traits<unsigned short>::reference reference;
282  typedef boost::gil::channel_traits<unsigned short>::const_reference const_reference;
283 };
284 
285 template <>
286 struct types_traits<int, false> {
287  typedef boost::gil::gray32s_image_t image_t;
288  typedef boost::gil::gray32s_view_t view_t;
289  typedef boost::gil::gray32sc_view_t const_view_t;
290  typedef boost::gil::channel_traits<int>::reference reference;
291  typedef boost::gil::channel_traits<int>::const_reference const_reference;
292 };
293 
294 template <>
295 struct types_traits<unsigned int, false> {
296  typedef boost::gil::gray32_image_t image_t;
297  typedef boost::gil::gray32_view_t view_t;
298  typedef boost::gil::gray32c_view_t const_view_t;
299  typedef boost::gil::channel_traits<int>::reference reference;
300  typedef boost::gil::channel_traits<int>::const_reference const_reference;
301 };
302 
303 template <>
304 struct types_traits<float, false> {
305  typedef boost::gil::gray32f_noscale_image_t image_t;
306  typedef boost::gil::gray32f_noscale_view_t view_t;
307  typedef boost::gil::gray32f_noscalec_view_t const_view_t;
308  typedef boost::gil::channel_traits<float>::reference reference;
309  typedef boost::gil::channel_traits<float>::const_reference const_reference;
310 };
311 
312 template <>
313 struct types_traits<long, false> {
314  typedef boost::gil::gray64s_image_t image_t;
315  typedef boost::gil::gray64s_view_t view_t;
316  typedef boost::gil::gray64sc_view_t const_view_t;
317  typedef boost::gil::channel_traits<long>::reference reference;
318  typedef boost::gil::channel_traits<long>::const_reference const_reference;
319 };
320 
321 template <>
322 struct types_traits<unsigned long, false> {
323  typedef boost::gil::gray64_image_t image_t;
324  typedef boost::gil::gray64_view_t view_t;
325  typedef boost::gil::gray64c_view_t const_view_t;
326  typedef boost::gil::channel_traits<long>::reference reference;
327  typedef boost::gil::channel_traits<long>::const_reference const_reference;
328 };
329 
330 namespace {
331 struct unknown {}; // two unused and unimplemented types
332 struct unknown_u {};
333 /*
334  * Return long long type (as type) if it's a synonym for std::int64_t
335  * We also need unsigned long long (as type_u), because "unsigned unknown" won't compile
336  */
337 struct CheckBoost64 {
338  typedef boost::mpl::if_<std::is_same<long long, std::int64_t>, long long, struct unknown>::type type;
339  typedef boost::mpl::if_<std::is_same<long long, std::int64_t>, unsigned long long, struct unknown_u>::type
340  type_u;
341 };
342 } // namespace
343 
344 template <>
345 struct types_traits<CheckBoost64::type, false> {
346  typedef boost::gil::gray64s_image_t image_t;
347  typedef boost::gil::gray64s_view_t view_t;
348  typedef boost::gil::gray64sc_view_t const_view_t;
349  typedef boost::gil::channel_traits<long>::reference reference;
350  typedef boost::gil::channel_traits<long>::const_reference const_reference;
351 };
352 
353 template <>
354 struct types_traits<CheckBoost64::type_u, false> {
355  typedef boost::gil::gray64_image_t image_t;
356  typedef boost::gil::gray64_view_t view_t;
357  typedef boost::gil::gray64c_view_t const_view_t;
358  typedef boost::gil::channel_traits<long>::reference reference;
359  typedef boost::gil::channel_traits<long>::const_reference const_reference;
360 };
361 
362 template <>
363 struct types_traits<double, false> {
364  typedef boost::gil::gray64f_noscale_image_t image_t;
365  typedef boost::gil::gray64f_noscale_view_t view_t;
366  typedef boost::gil::gray64f_noscalec_view_t const_view_t;
367  typedef boost::gil::channel_traits<double>::reference reference;
368  typedef boost::gil::channel_traits<double>::const_reference const_reference;
369 };
370 
371 template <typename T>
372 struct const_iterator_type {
374 };
375 
376 template <typename T>
377 struct const_locator_type { // should assert that T is a locator
378  typedef typename T::const_t type;
379 };
380 
381 typedef boost::gil::point2<std::ptrdiff_t> difference_type; // type used to advance locators
382 }
383 } // namespace image
384 } // namespace afw
385 } // namespace lsst
386 
387 namespace boost {
388 namespace gil {
389 
391 template <typename View1, typename View2, typename View3, typename ViewDest, typename F>
392 BOOST_FORCEINLINE F transform_pixels(const View1& src1, const View2& src2, const View3& src3,
393  const ViewDest& dst, F fun) {
394  for (std::ptrdiff_t y = 0; y < dst.height(); ++y) {
395  typename View1::x_iterator srcIt1 = src1.row_begin(y);
396  typename View2::x_iterator srcIt2 = src2.row_begin(y);
397  typename View3::x_iterator srcIt3 = src3.row_begin(y);
398  typename ViewDest::x_iterator dstIt = dst.row_begin(y);
399  for (std::ptrdiff_t x = 0; x < dst.width(); ++x) dstIt[x] = fun(srcIt1[x], srcIt2[x], srcIt3[x]);
400  }
401  return fun;
402 }
403 
405 template <typename View1, typename View2, typename View3, typename View4, typename ViewDest, typename F>
406 BOOST_FORCEINLINE F transform_pixels(const View1& src1, const View2& src2, const View3& src3, const View4& src4,
407  const ViewDest& dst, F fun) {
408  for (std::ptrdiff_t y = 0; y < dst.height(); ++y) {
409  typename View1::x_iterator srcIt1 = src1.row_begin(y);
410  typename View2::x_iterator srcIt2 = src2.row_begin(y);
411  typename View3::x_iterator srcIt3 = src3.row_begin(y);
412  typename View4::x_iterator srcIt4 = src4.row_begin(y);
413  typename ViewDest::x_iterator dstIt = dst.row_begin(y);
414  for (std::ptrdiff_t x = 0; x < dst.width(); ++x)
415  dstIt[x] = fun(srcIt1[x], srcIt2[x], srcIt3[x], srcIt4[x]);
416  }
417  return fun;
418 }
419 } // namespace gil
420 } // namespace boost
421 #endif
422 
y
int y
Definition: SpanSet.cc:49
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
std::binary_function
lsst::afw::table._match.second
second
Definition: _match.py:78
std::pair
lsst::afw::table._match.first
first
Definition: _match.py:76
lsst::afw
Definition: imageAlgorithm.dox:1
boost
Definition: Polygon.cc:25
x
double x
Definition: ChebyshevBoundedField.cc:277
lsst::afw::image::operator-=
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:677
b
table::Key< int > b
Definition: TransmissionCurve.cc:467
std::unary_function
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
a
table::Key< int > a
Definition: TransmissionCurve.cc:466
std
STL namespace.
type
table::Key< int > type
Definition: Detector.cc:163
std::ptrdiff_t
lsst::afw::image::operator+=
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:671