Grok 10.0.5
image.h
Go to the documentation of this file.
1// Copyright 2020 Google LLC
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#ifndef HIGHWAY_HWY_CONTRIB_IMAGE_IMAGE_H_
17#define HIGHWAY_HWY_CONTRIB_IMAGE_IMAGE_H_
18
19// SIMD/multicore-friendly planar image representation with row accessors.
20
21#include <stddef.h>
22#include <stdint.h>
23#include <string.h>
24
25#include <utility> // std::move
26
28#include "hwy/base.h"
29#include "hwy/highway_export.h"
30
31namespace hwy {
32
33// Type-independent parts of Image<> - reduces code duplication and facilitates
34// moving member function implementations to cc file.
36 // Returns required alignment in bytes for externally allocated memory.
37 static size_t VectorSize();
38
39 // Returns distance [bytes] between the start of two consecutive rows, a
40 // multiple of VectorSize but NOT kAlias (see implementation).
41 static size_t BytesPerRow(const size_t xsize, const size_t sizeof_t);
42
43 // No allocation (for output params or unused images)
45 : xsize_(0),
46 ysize_(0),
47 bytes_per_row_(0),
48 bytes_(nullptr, AlignedFreer(&AlignedFreer::DoNothing, nullptr)) {}
49
50 // Allocates memory (this is the common case)
51 ImageBase(size_t xsize, size_t ysize, size_t sizeof_t);
52
53 // References but does not take ownership of external memory. Useful for
54 // interoperability with other libraries. `aligned` must be aligned to a
55 // multiple of VectorSize() and `bytes_per_row` must also be a multiple of
56 // VectorSize() or preferably equal to BytesPerRow().
57 ImageBase(size_t xsize, size_t ysize, size_t bytes_per_row, void* aligned);
58
59 // Copy construction/assignment is forbidden to avoid inadvertent copies,
60 // which can be very expensive. Use CopyImageTo() instead.
61 ImageBase(const ImageBase& other) = delete;
62 ImageBase& operator=(const ImageBase& other) = delete;
63
64 // Move constructor (required for returning Image from function)
65 ImageBase(ImageBase&& other) noexcept = default;
66
67 // Move assignment (required for std::vector)
68 ImageBase& operator=(ImageBase&& other) noexcept = default;
69
70 void Swap(ImageBase& other);
71
72 // Useful for pre-allocating image with some padding for alignment purposes
73 // and later reporting the actual valid dimensions. Caller is responsible
74 // for ensuring xsize/ysize are <= the original dimensions.
75 void ShrinkTo(const size_t xsize, const size_t ysize) {
76 xsize_ = static_cast<uint32_t>(xsize);
77 ysize_ = static_cast<uint32_t>(ysize);
78 // NOTE: we can't recompute bytes_per_row for more compact storage and
79 // better locality because that would invalidate the image contents.
80 }
81
82 // How many pixels.
83 HWY_INLINE size_t xsize() const { return xsize_; }
84 HWY_INLINE size_t ysize() const { return ysize_; }
85
86 // NOTE: do not use this for copying rows - the valid xsize may be much less.
87 HWY_INLINE size_t bytes_per_row() const { return bytes_per_row_; }
88
89 // Raw access to byte contents, for interfacing with other libraries.
90 // Unsigned char instead of char to avoid surprises (sign extension).
91 HWY_INLINE uint8_t* bytes() {
92 void* p = bytes_.get();
93 return static_cast<uint8_t * HWY_RESTRICT>(HWY_ASSUME_ALIGNED(p, 64));
94 }
95 HWY_INLINE const uint8_t* bytes() const {
96 const void* p = bytes_.get();
97 return static_cast<const uint8_t * HWY_RESTRICT>(HWY_ASSUME_ALIGNED(p, 64));
98 }
99
100 protected:
101 // Returns pointer to the start of a row.
102 HWY_INLINE void* VoidRow(const size_t y) const {
103#if HWY_IS_ASAN || HWY_IS_MSAN || HWY_IS_TSAN
104 if (y >= ysize_) {
105 HWY_ABORT("Row(%d) >= %u\n", static_cast<int>(y), ysize_);
106 }
107#endif
108
109 void* row = bytes_.get() + y * bytes_per_row_;
110 return HWY_ASSUME_ALIGNED(row, 64);
111 }
112
113 enum class Padding {
114 // Allow Load(d, row + x) for x = 0; x < xsize(); x += Lanes(d). Default.
115 kRoundUp,
116 // Allow LoadU(d, row + x) for x <= xsize() - 1. This requires an extra
117 // vector to be initialized. If done by default, this would suppress
118 // legitimate msan warnings. We therefore require users to explicitly call
119 // InitializePadding before using unaligned loads (e.g. convolution).
120 kUnaligned
121 };
122
123 // Initializes the minimum bytes required to suppress msan warnings from
124 // legitimate (according to Padding mode) vector loads/stores on the right
125 // border, where some lanes are uninitialized and assumed to be unused.
126 void InitializePadding(size_t sizeof_t, Padding padding);
127
128 // (Members are non-const to enable assignment during move-assignment.)
129 uint32_t xsize_; // In valid pixels, not including any padding.
130 uint32_t ysize_;
131 size_t bytes_per_row_; // Includes padding.
133};
134
135// Single channel, aligned rows separated by padding. T must be POD.
136//
137// 'Single channel' (one 2D array per channel) simplifies vectorization
138// (repeating the same operation on multiple adjacent components) without the
139// complexity of a hybrid layout (8 R, 8 G, 8 B, ...). In particular, clients
140// can easily iterate over all components in a row and Image requires no
141// knowledge of the pixel format beyond the component type "T".
142//
143// 'Aligned' means each row is aligned to the L1 cache line size. This prevents
144// false sharing between two threads operating on adjacent rows.
145//
146// 'Padding' is still relevant because vectors could potentially be larger than
147// a cache line. By rounding up row sizes to the vector size, we allow
148// reading/writing ALIGNED vectors whose first lane is a valid sample. This
149// avoids needing a separate loop to handle remaining unaligned lanes.
150//
151// This image layout could also be achieved with a vector and a row accessor
152// function, but a class wrapper with support for "deleter" allows wrapping
153// existing memory allocated by clients without copying the pixels. It also
154// provides convenient accessors for xsize/ysize, which shortens function
155// argument lists. Supports move-construction so it can be stored in containers.
156template <typename ComponentType>
157class Image : public ImageBase {
158 public:
159 using T = ComponentType;
160
161 Image() = default;
162 Image(const size_t xsize, const size_t ysize)
163 : ImageBase(xsize, ysize, sizeof(T)) {}
164 Image(const size_t xsize, const size_t ysize, size_t bytes_per_row,
165 void* aligned)
166 : ImageBase(xsize, ysize, bytes_per_row, aligned) {}
167
171
172 HWY_INLINE const T* ConstRow(const size_t y) const {
173 return static_cast<const T*>(VoidRow(y));
174 }
175 HWY_INLINE const T* ConstRow(const size_t y) {
176 return static_cast<const T*>(VoidRow(y));
177 }
178
179 // Returns pointer to non-const. This allows passing const Image* parameters
180 // when the callee is only supposed to fill the pixels, as opposed to
181 // allocating or resizing the image.
182 HWY_INLINE T* MutableRow(const size_t y) const {
183 return static_cast<T*>(VoidRow(y));
184 }
185 HWY_INLINE T* MutableRow(const size_t y) {
186 return static_cast<T*>(VoidRow(y));
187 }
188
189 // Returns number of pixels (some of which are padding) per row. Useful for
190 // computing other rows via pointer arithmetic. WARNING: this must
191 // NOT be used to determine xsize.
192 HWY_INLINE intptr_t PixelsPerRow() const {
193 return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
194 }
195};
196
198
199// A bundle of 3 same-sized images. To fill an existing Image3 using
200// single-channel producers, we also need access to each const Image*. Const
201// prevents breaking the same-size invariant, while still allowing pixels to be
202// changed via MutableRow.
203template <typename ComponentType>
204class Image3 {
205 public:
206 using T = ComponentType;
208 static constexpr size_t kNumPlanes = 3;
209
211
212 Image3(const size_t xsize, const size_t ysize)
214 ImageT(xsize, ysize)} {}
215
216 Image3(Image3&& other) noexcept {
217 for (size_t i = 0; i < kNumPlanes; i++) {
218 planes_[i] = std::move(other.planes_[i]);
219 }
220 }
221
222 Image3(ImageT&& plane0, ImageT&& plane1, ImageT&& plane2) {
223 if (!SameSize(plane0, plane1) || !SameSize(plane0, plane2)) {
224 HWY_ABORT(
225 "Not same size: %d x %d, %d x %d, %d x %d\n",
226 static_cast<int>(plane0.xsize()), static_cast<int>(plane0.ysize()),
227 static_cast<int>(plane1.xsize()), static_cast<int>(plane1.ysize()),
228 static_cast<int>(plane2.xsize()), static_cast<int>(plane2.ysize()));
229 }
230 planes_[0] = std::move(plane0);
231 planes_[1] = std::move(plane1);
232 planes_[2] = std::move(plane2);
233 }
234
235 // Copy construction/assignment is forbidden to avoid inadvertent copies,
236 // which can be very expensive. Use CopyImageTo instead.
237 Image3(const Image3& other) = delete;
238 Image3& operator=(const Image3& other) = delete;
239
240 Image3& operator=(Image3&& other) noexcept {
241 for (size_t i = 0; i < kNumPlanes; i++) {
242 planes_[i] = std::move(other.planes_[i]);
243 }
244 return *this;
245 }
246
247 HWY_INLINE const T* ConstPlaneRow(const size_t c, const size_t y) const {
248 return static_cast<const T*>(VoidPlaneRow(c, y));
249 }
250 HWY_INLINE const T* ConstPlaneRow(const size_t c, const size_t y) {
251 return static_cast<const T*>(VoidPlaneRow(c, y));
252 }
253
254 HWY_INLINE T* MutablePlaneRow(const size_t c, const size_t y) const {
255 return static_cast<T*>(VoidPlaneRow(c, y));
256 }
257 HWY_INLINE T* MutablePlaneRow(const size_t c, const size_t y) {
258 return static_cast<T*>(VoidPlaneRow(c, y));
259 }
260
261 HWY_INLINE const ImageT& Plane(size_t idx) const { return planes_[idx]; }
262
263 void Swap(Image3& other) {
264 for (size_t c = 0; c < 3; ++c) {
265 other.planes_[c].Swap(planes_[c]);
266 }
267 }
268
269 void ShrinkTo(const size_t xsize, const size_t ysize) {
270 for (ImageT& plane : planes_) {
271 plane.ShrinkTo(xsize, ysize);
272 }
273 }
274
275 // Sizes of all three images are guaranteed to be equal.
276 HWY_INLINE size_t xsize() const { return planes_[0].xsize(); }
277 HWY_INLINE size_t ysize() const { return planes_[0].ysize(); }
278 // Returns offset [bytes] from one row to the next row of the same plane.
279 // WARNING: this must NOT be used to determine xsize, nor for copying rows -
280 // the valid xsize may be much less.
281 HWY_INLINE size_t bytes_per_row() const { return planes_[0].bytes_per_row(); }
282 // Returns number of pixels (some of which are padding) per row. Useful for
283 // computing other rows via pointer arithmetic. WARNING: this must NOT be used
284 // to determine xsize.
285 HWY_INLINE intptr_t PixelsPerRow() const { return planes_[0].PixelsPerRow(); }
286
287 private:
288 // Returns pointer to the start of a row.
289 HWY_INLINE void* VoidPlaneRow(const size_t c, const size_t y) const {
290#if HWY_IS_ASAN || HWY_IS_MSAN || HWY_IS_TSAN
291 if (c >= kNumPlanes || y >= ysize()) {
292 HWY_ABORT("PlaneRow(%d, %d) >= %d\n", static_cast<int>(c),
293 static_cast<int>(y), static_cast<int>(ysize()));
294 }
295#endif
296 // Use the first plane's stride because the compiler might not realize they
297 // are all equal. Thus we only need a single multiplication for all planes.
298 const size_t row_offset = y * planes_[0].bytes_per_row();
299 const void* row = planes_[c].bytes() + row_offset;
300 return static_cast<const T * HWY_RESTRICT>(
302 }
303
304 private:
306};
307
309
310// Rectangular region in image(s). Factoring this out of Image instead of
311// shifting the pointer by x0/y0 allows this to apply to multiple images with
312// different resolutions. Can compare size via SameSize(rect1, rect2).
313class Rect {
314 public:
315 // Most windows are xsize_max * ysize_max, except those on the borders where
316 // begin + size_max > end.
317 constexpr Rect(size_t xbegin, size_t ybegin, size_t xsize_max,
318 size_t ysize_max, size_t xend, size_t yend)
319 : x0_(xbegin),
320 y0_(ybegin),
321 xsize_(ClampedSize(xbegin, xsize_max, xend)),
322 ysize_(ClampedSize(ybegin, ysize_max, yend)) {}
323
324 // Construct with origin and known size (typically from another Rect).
325 constexpr Rect(size_t xbegin, size_t ybegin, size_t xsize, size_t ysize)
326 : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {}
327
328 // Construct a rect that covers a whole image.
329 template <typename Image>
330 explicit Rect(const Image& image)
331 : Rect(0, 0, image.xsize(), image.ysize()) {}
332
333 Rect() : Rect(0, 0, 0, 0) {}
334
335 Rect(const Rect&) = default;
336 Rect& operator=(const Rect&) = default;
337
338 Rect Subrect(size_t xbegin, size_t ybegin, size_t xsize_max,
339 size_t ysize_max) {
340 return Rect(x0_ + xbegin, y0_ + ybegin, xsize_max, ysize_max, x0_ + xsize_,
341 y0_ + ysize_);
342 }
343
344 template <typename T>
345 const T* ConstRow(const Image<T>* image, size_t y) const {
346 return image->ConstRow(y + y0_) + x0_;
347 }
348
349 template <typename T>
350 T* MutableRow(const Image<T>* image, size_t y) const {
351 return image->MutableRow(y + y0_) + x0_;
352 }
353
354 template <typename T>
355 const T* ConstPlaneRow(const Image3<T>& image, size_t c, size_t y) const {
356 return image.ConstPlaneRow(c, y + y0_) + x0_;
357 }
358
359 template <typename T>
360 T* MutablePlaneRow(Image3<T>* image, const size_t c, size_t y) const {
361 return image->MutablePlaneRow(c, y + y0_) + x0_;
362 }
363
364 // Returns true if this Rect fully resides in the given image. ImageT could be
365 // Image<T> or Image3<T>; however if ImageT is Rect, results are nonsensical.
366 template <class ImageT>
367 bool IsInside(const ImageT& image) const {
368 return (x0_ + xsize_ <= image.xsize()) && (y0_ + ysize_ <= image.ysize());
369 }
370
371 size_t x0() const { return x0_; }
372 size_t y0() const { return y0_; }
373 size_t xsize() const { return xsize_; }
374 size_t ysize() const { return ysize_; }
375
376 private:
377 // Returns size_max, or whatever is left in [begin, end).
378 static constexpr size_t ClampedSize(size_t begin, size_t size_max,
379 size_t end) {
380 return (begin + size_max <= end) ? size_max
381 : (end > begin ? end - begin : 0);
382 }
383
384 size_t x0_;
385 size_t y0_;
386
387 size_t xsize_;
388 size_t ysize_;
389};
390
391// Works for any image-like input type(s).
392template <class Image1, class Image2>
393HWY_MAYBE_UNUSED bool SameSize(const Image1& image1, const Image2& image2) {
394 return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
395}
396
397// Mirrors out of bounds coordinates and returns valid coordinates unchanged.
398// We assume the radius (distance outside the image) is small compared to the
399// image size, otherwise this might not terminate.
400// The mirror is outside the last column (border pixel is also replicated).
401static HWY_INLINE HWY_MAYBE_UNUSED size_t Mirror(int64_t x,
402 const int64_t xsize) {
403 HWY_DASSERT(xsize != 0);
404
405 // TODO(janwas): replace with branchless version
406 while (x < 0 || x >= xsize) {
407 if (x < 0) {
408 x = -x - 1;
409 } else {
410 x = 2 * xsize - 1 - x;
411 }
412 }
413 return static_cast<size_t>(x);
414}
415
416// Wrap modes for ensuring X/Y coordinates are in the valid range [0, size):
417
418// Mirrors (repeating the edge pixel once). Useful for convolutions.
420 HWY_INLINE size_t operator()(const int64_t coord, const size_t size) const {
421 return Mirror(coord, static_cast<int64_t>(size));
422 }
423};
424
425// Returns the same coordinate, for when we know "coord" is already valid (e.g.
426// interior of an image).
428 HWY_INLINE size_t operator()(const int64_t coord, size_t /*size*/) const {
429 return static_cast<size_t>(coord);
430 }
431};
432
433// Similar to Wrap* but for row pointers (reduces Row() multiplications).
434
436 public:
437 template <class View>
438 WrapRowMirror(const View& image, size_t ysize)
439 : first_row_(image.ConstRow(0)), last_row_(image.ConstRow(ysize - 1)) {}
440
441 const float* operator()(const float* const HWY_RESTRICT row,
442 const int64_t stride) const {
443 if (row < first_row_) {
444 const int64_t num_before = first_row_ - row;
445 // Mirrored; one row before => row 0, two before = row 1, ...
446 return first_row_ + num_before - stride;
447 }
448 if (row > last_row_) {
449 const int64_t num_after = row - last_row_;
450 // Mirrored; one row after => last row, two after = last - 1, ...
451 return last_row_ - num_after + stride;
452 }
453 return row;
454 }
455
456 private:
457 const float* const HWY_RESTRICT first_row_;
458 const float* const HWY_RESTRICT last_row_;
459};
460
462 HWY_INLINE const float* operator()(const float* const HWY_RESTRICT row,
463 int64_t /*stride*/) const {
464 return row;
465 }
466};
467
468} // namespace hwy
469
470#endif // HIGHWAY_HWY_CONTRIB_IMAGE_IMAGE_H_
#define HWY_ALIGNMENT
Definition aligned_allocator.h:32
#define HWY_RESTRICT
Definition base.h:64
#define HWY_ABORT(format,...)
Definition base.h:188
#define HWY_INLINE
Definition base.h:70
#define HWY_DASSERT(condition)
Definition base.h:238
#define HWY_MAYBE_UNUSED
Definition base.h:82
#define HWY_ASSUME_ALIGNED(ptr, align)
Definition base.h:106
Definition aligned_allocator.h:170
Definition image.h:204
ImageT planes_[kNumPlanes]
Definition image.h:305
Image3(const Image3 &other)=delete
Image3 & operator=(Image3 &&other) noexcept
Definition image.h:240
HWY_INLINE size_t xsize() const
Definition image.h:276
HWY_INLINE size_t ysize() const
Definition image.h:277
HWY_INLINE T * MutablePlaneRow(const size_t c, const size_t y) const
Definition image.h:254
Image3(Image3 &&other) noexcept
Definition image.h:216
Image3(const size_t xsize, const size_t ysize)
Definition image.h:212
Image3(ImageT &&plane0, ImageT &&plane1, ImageT &&plane2)
Definition image.h:222
Image3()
Definition image.h:210
HWY_INLINE const T * ConstPlaneRow(const size_t c, const size_t y)
Definition image.h:250
HWY_INLINE const T * ConstPlaneRow(const size_t c, const size_t y) const
Definition image.h:247
HWY_INLINE const ImageT & Plane(size_t idx) const
Definition image.h:261
ComponentType T
Definition image.h:206
void ShrinkTo(const size_t xsize, const size_t ysize)
Definition image.h:269
HWY_INLINE T * MutablePlaneRow(const size_t c, const size_t y)
Definition image.h:257
HWY_INLINE void * VoidPlaneRow(const size_t c, const size_t y) const
Definition image.h:289
HWY_INLINE intptr_t PixelsPerRow() const
Definition image.h:285
static constexpr size_t kNumPlanes
Definition image.h:208
Image3 & operator=(const Image3 &other)=delete
HWY_INLINE size_t bytes_per_row() const
Definition image.h:281
void Swap(Image3 &other)
Definition image.h:263
Definition image.h:157
Image()=default
HWY_INLINE intptr_t PixelsPerRow() const
Definition image.h:192
void InitializePaddingForUnalignedAccesses()
Definition image.h:168
HWY_INLINE T * MutableRow(const size_t y)
Definition image.h:185
Image(const size_t xsize, const size_t ysize, size_t bytes_per_row, void *aligned)
Definition image.h:164
HWY_INLINE const T * ConstRow(const size_t y)
Definition image.h:175
ComponentType T
Definition image.h:159
HWY_INLINE T * MutableRow(const size_t y) const
Definition image.h:182
HWY_INLINE const T * ConstRow(const size_t y) const
Definition image.h:172
Image(const size_t xsize, const size_t ysize)
Definition image.h:162
Definition image.h:313
constexpr Rect(size_t xbegin, size_t ybegin, size_t xsize_max, size_t ysize_max, size_t xend, size_t yend)
Definition image.h:317
T * MutableRow(const Image< T > *image, size_t y) const
Definition image.h:350
T * MutablePlaneRow(Image3< T > *image, const size_t c, size_t y) const
Definition image.h:360
size_t x0_
Definition image.h:384
size_t xsize() const
Definition image.h:373
static constexpr size_t ClampedSize(size_t begin, size_t size_max, size_t end)
Definition image.h:378
const T * ConstRow(const Image< T > *image, size_t y) const
Definition image.h:345
bool IsInside(const ImageT &image) const
Definition image.h:367
Rect(const Image &image)
Definition image.h:330
const T * ConstPlaneRow(const Image3< T > &image, size_t c, size_t y) const
Definition image.h:355
Rect Subrect(size_t xbegin, size_t ybegin, size_t xsize_max, size_t ysize_max)
Definition image.h:338
Rect & operator=(const Rect &)=default
size_t xsize_
Definition image.h:387
size_t y0_
Definition image.h:385
constexpr Rect(size_t xbegin, size_t ybegin, size_t xsize, size_t ysize)
Definition image.h:325
Rect()
Definition image.h:333
size_t ysize() const
Definition image.h:374
Rect(const Rect &)=default
size_t ysize_
Definition image.h:388
size_t x0() const
Definition image.h:371
size_t y0() const
Definition image.h:372
Definition image.h:435
const float *const HWY_RESTRICT first_row_
Definition image.h:457
const float *const HWY_RESTRICT last_row_
Definition image.h:458
const float * operator()(const float *const HWY_RESTRICT row, const int64_t stride) const
Definition image.h:441
WrapRowMirror(const View &image, size_t ysize)
Definition image.h:438
#define HWY_CONTRIB_DLLEXPORT
Definition highway_export.h:14
Definition aligned_allocator.h:27
HWY_MAYBE_UNUSED bool SameSize(const Image1 &image1, const Image2 &image2)
Definition image.h:393
static HWY_INLINE HWY_MAYBE_UNUSED size_t Mirror(int64_t x, const int64_t xsize)
Definition image.h:401
std::unique_ptr< T, AlignedFreer > AlignedFreeUniquePtr
Definition aligned_allocator.h:193
Definition image.h:35
Padding
Definition image.h:113
HWY_INLINE uint8_t * bytes()
Definition image.h:91
static size_t VectorSize()
HWY_INLINE size_t xsize() const
Definition image.h:83
HWY_INLINE const uint8_t * bytes() const
Definition image.h:95
void Swap(ImageBase &other)
HWY_INLINE void * VoidRow(const size_t y) const
Definition image.h:102
size_t bytes_per_row_
Definition image.h:131
void ShrinkTo(const size_t xsize, const size_t ysize)
Definition image.h:75
ImageBase()
Definition image.h:44
HWY_INLINE size_t ysize() const
Definition image.h:84
static size_t BytesPerRow(const size_t xsize, const size_t sizeof_t)
uint32_t xsize_
Definition image.h:129
AlignedFreeUniquePtr< uint8_t[]> bytes_
Definition image.h:132
ImageBase(size_t xsize, size_t ysize, size_t bytes_per_row, void *aligned)
ImageBase(ImageBase &&other) noexcept=default
ImageBase & operator=(const ImageBase &other)=delete
uint32_t ysize_
Definition image.h:130
ImageBase(const ImageBase &other)=delete
void InitializePadding(size_t sizeof_t, Padding padding)
HWY_INLINE size_t bytes_per_row() const
Definition image.h:87
ImageBase(size_t xsize, size_t ysize, size_t sizeof_t)
ImageBase & operator=(ImageBase &&other) noexcept=default
Definition image.h:419
HWY_INLINE size_t operator()(const int64_t coord, const size_t size) const
Definition image.h:420
Definition image.h:461
HWY_INLINE const float * operator()(const float *const HWY_RESTRICT row, int64_t) const
Definition image.h:462
Definition image.h:427
HWY_INLINE size_t operator()(const int64_t coord, size_t) const
Definition image.h:428