LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
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
54namespace lsst {
55namespace afw {
56namespace 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 */
64struct 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
75template <typename T>
76boost::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}
83template <typename T>
84boost::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
91namespace boost {
92namespace gil {
97template <typename T>
98memory_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}
105template <typename T>
106memory_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 */
113using bits64 = uint64_t;
114using bits64s = int64_t;
115
116BOOST_GIL_DEFINE_BASE_TYPEDEFS(64, bits64, gray)
117BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(64, bits64, dev2n, devicen_t<2>, devicen_layout_t<2>)
118BOOST_GIL_DEFINE_BASE_TYPEDEFS(64s, bits64s, gray)
119BOOST_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 */
124using bits32f_noscale = float;
125
126BOOST_GIL_DEFINE_BASE_TYPEDEFS(32f_noscale, bits32f_noscale, gray)
127BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f_noscale, bits32f_noscale, dev2n, devicen_t<2>, devicen_layout_t<2>)
128
129template <>
130struct 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 */
138using bits64f_noscale = double;
139
140BOOST_GIL_DEFINE_BASE_TYPEDEFS(64f_noscale, bits64f_noscale, gray)
141BOOST_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//
146template <typename DstChannelV>
147struct 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
152template <typename SrcChannelV>
153struct 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
158template <typename DstChannelV>
159struct 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
164template <typename SrcChannelV>
165struct 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
184LSST_CONVERT_NOOP(bits32f_noscale, bits64f_noscale);
185
186LSST_CONVERT_NOOP(unsigned char, short);
187LSST_CONVERT_NOOP(unsigned char, unsigned short);
188LSST_CONVERT_NOOP(unsigned char, int);
189LSST_CONVERT_NOOP(unsigned short, short);
190LSST_CONVERT_NOOP(unsigned short, int);
191LSST_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
213LSST_BOOST_GIL_OP_EQUALS_ALL(gray8)
214LSST_BOOST_GIL_OP_EQUALS_ALL(gray8s)
215LSST_BOOST_GIL_OP_EQUALS_ALL(gray16)
216LSST_BOOST_GIL_OP_EQUALS_ALL(gray16s)
217LSST_BOOST_GIL_OP_EQUALS_ALL(gray32)
218LSST_BOOST_GIL_OP_EQUALS_ALL(gray32s)
219LSST_BOOST_GIL_OP_EQUALS_ALL(gray32f_noscale)
220LSST_BOOST_GIL_OP_EQUALS_ALL(gray64)
221LSST_BOOST_GIL_OP_EQUALS_ALL(gray64s)
222LSST_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
229namespace lsst {
230namespace afw {
231namespace image {
232namespace detail {
233//
234// Map typenames to gil's types
235//
236
237template <typename T, bool rescale = false>
238struct 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
243template <>
244struct 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
252template <>
253struct 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
261template <>
262struct 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
270template <>
271struct 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
279template <>
280struct 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
288template <>
289struct 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
297template <>
298struct 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
306template <>
307struct 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
315namespace {
316struct unknown {}; // two unused and unimplemented types
317struct 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 */
322struct 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
328template <>
329struct 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
337template <>
338struct 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
346template <>
347struct 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
355template <typename T>
356struct const_iterator_type {
357 using type = typename boost::gil::const_iterator_type<T>::type;
358};
359
360template <typename T>
361struct const_locator_type { // should assert that T is a locator
362 using type = typename T::const_t;
363};
364
365using difference_type = boost::gil::point2<std::ptrdiff_t>; // type used to advance locators
366}
367} // namespace image
368} // namespace afw
369} // namespace lsst
370
371namespace boost {
372namespace gil {
373
375template <typename View1, typename View2, typename View3, typename ViewDest, typename F>
376BOOST_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
389template <typename View1, typename View2, typename View3, typename View4, typename ViewDest, typename F>
390BOOST_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
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:698
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:704
STL namespace.