array
C++ library for multi-dimensional arrays
image.h
Go to the documentation of this file.
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
18 #ifndef NDARRAY_IMAGE_H
19 #define NDARRAY_IMAGE_H
20 
21 #include "array/array.h"
22 
23 namespace nda {
24 
28 using image_shape = shape<dim<>, dim<>, dim<>>;
29 template <class T, class Alloc = std::allocator<T>>
31 template <class T>
33 template <class T>
35 
41 template <index_t Channels = dynamic, index_t XStride = Channels>
43 template <class T, index_t Channels = dynamic, index_t XStride = Channels,
44  class Alloc = std::allocator<T>>
46 template <class T, index_t Channels = dynamic, index_t XStride = Channels>
48 template <class T, index_t Channels = dynamic, index_t XStride = Channels>
50 
53 template <class Shape, class Fn>
54 void for_each_image_index(const Shape& s, Fn&& fn) {
55  // Images should always be iterated with c as the innermost loop. Even when
56  // the image is planar, the number of channels is generally small, and many
57  // operations use all of the channels at the same time (all-to-all
58  // communication in the c dimension).
59  for (index_t y : s.y()) {
60  for (index_t x : s.x()) {
61  for (index_t c : s.c()) {
62  fn(std::tuple<index_t, index_t, index_t>(x, y, c));
63  }
64  }
65  }
66 }
67 
68 template <index_t Channels, index_t XStride>
69 class shape_traits<chunky_image_shape<Channels, XStride>> {
70 public:
72 
73  template <class Fn>
74  static void for_each_index(const shape_type& s, Fn&& fn) {
75  for_each_image_index(s, fn);
76  }
77 
78  template <class Ptr, class Fn>
79  static void for_each_value(const shape_type& s, Ptr base, Fn&& fn) {
81  s, [=, fn = std::move(fn)](const typename shape_type::index_type& i) { fn(base[s[i]]); });
82  }
83 };
84 
85 template <index_t Channels>
86 class shape_traits<chunky_image_shape<Channels>> {
87 public:
89 
90  template <class Fn>
91  static void for_each_index(const shape_type& s, Fn&& fn) {
92  for_each_image_index(s, fn);
93  }
94 
95  // When Channels == XStride, we can implement for_each_value by fusing
96  // the x and c dimensions.
97  template <class Ptr, class Fn>
98  static void for_each_value(const shape_type& s, Ptr base, Fn&& fn) {
99  const index_t channels = s.c().extent();
100  if (channels == s.x().stride()) {
101  dense_shape<2> opt_s({s.x().min() * channels, s.x().extent() * channels}, s.y());
102  for_each_value_in_order(opt_s, base, fn);
103  } else {
104  for_each_value_in_order(s, base, fn);
105  }
106  }
107 };
108 
113 using planar_image_shape = shape<dense_dim<>, dim<>, dim<>>;
114 template <class T, class Alloc = std::allocator<T>>
116 template <class T>
118 template <class T>
120 
121 enum class crop_origin {
123  zero,
126  crop,
127 };
128 
131 template <class Shape>
132 Shape crop_image_shape(Shape s, index_t x0, index_t y0, index_t x1, index_t y1,
133  crop_origin origin = crop_origin::crop) {
134  s.x().set_extent(x1 - x0);
135  s.y().set_extent(y1 - y0);
136  switch (origin) {
137  case crop_origin::zero:
138  s.x().set_min(0);
139  s.y().set_min(0);
140  break;
141  case crop_origin::crop:
142  s.x().set_min(x0);
143  s.y().set_min(y0);
144  break;
145  }
146  return s;
147 }
148 
152 template <class T, class Shape>
154  index_t y1, crop_origin origin = crop_origin::crop) {
155  x0 = internal::max(x0, im.x().min());
156  y0 = internal::max(y0, im.y().min());
157  x1 = internal::min(x1, im.x().max() + 1);
158  y1 = internal::min(y1, im.y().max() + 1);
159  Shape cropped_shape = crop_image_shape(im.shape(), x0, y0, x1, y1, origin);
160  index_t c0 = im.c().min();
161  T* base = im.base() != nullptr ? &im(x0, y0, c0) : nullptr;
162  if (origin == crop_origin::crop) {
163  base = internal::pointer_add(base, -cropped_shape(x0, y0, c0));
164  }
165  return array_ref<T, Shape>(base, cropped_shape);
166 }
167 template <class T, class Shape>
169  index_t y1, crop_origin origin = crop_origin::crop) {
170  return crop(im.ref(), x0, y0, x1, y1, origin);
171 }
172 template <class T, class Shape>
174  crop_origin origin = crop_origin::crop) {
175  return crop(im.ref(), x0, y0, x1, y1, origin);
176 }
177 
180 template <class T, class Shape>
181 auto slice_channel(const array_ref<T, Shape>& im, index_t channel) {
182  return im(im.x(), im.y(), channel);
183 }
184 template <class T, class Shape, class Alloc>
185 auto slice_channel(const array<T, Shape, Alloc>& im, index_t channel) {
186  return slice_channel(im.ref(), channel);
187 }
188 template <class T, class Shape, class Alloc>
189 auto slice_channel(array<T, Shape, Alloc>& im, index_t channel) {
190  return slice_channel(im.ref(), channel);
191 }
192 
193 } // namespace nda
194 
195 #endif // NDARRAY_IMAGE_H
NDARRAY_HOST_DEVICE Shape & shape()
Definition: array.h:2105
constexpr index_t dynamic
Definition: array.h:99
index_of_rank< rank()> index_type
Definition: array.h:1076
Definition: array.h:1036
static NDARRAY_HOST_DEVICE void for_each_value(const Shape &shape, Ptr base, Fn &&fn)
Definition: array.h:1882
Definition: array.h:1961
Definition: array.h:1963
NDARRAY_HOST_DEVICE pointer base() const
Definition: array.h:2096
Shape crop_image_shape(Shape s, index_t x0, index_t y0, index_t x1, index_t y1, crop_origin origin=crop_origin::crop)
Definition: image.h:132
NDARRAY_HOST_DEVICE auto & x()
Definition: array.h:1274
Main header for array library.
Definition: absl.h:10
auto slice_channel(const array_ref< T, Shape > &im, index_t channel)
Definition: image.h:181
Definition: array.h:1867
array_ref< T, Shape > crop(const array_ref< T, Shape > &im, index_t x0, index_t y0, index_t x1, index_t y1, crop_origin origin=crop_origin::crop)
Definition: image.h:153
NDARRAY_HOST_DEVICE auto & x()
Definition: array.h:2132
void for_each_image_index(const Shape &s, Fn &&fn)
Definition: image.h:54
std::ptrdiff_t index_t
Definition: array.h:87
Definition: array.h:231
static NDARRAY_HOST_DEVICE void for_each_index(const Shape &shape, Fn &&fn)
Definition: array.h:1874
array_ref< T, Shape > ref()
Definition: array.h:2675
decltype(internal::make_default_dense_shape< Rank >()) dense_shape
Definition: array.h:1606