Coverage Report

Created: 2022-08-24 06:33

/src/libjxl/lib/jxl/image.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2
//
3
// Use of this source code is governed by a BSD-style
4
// license that can be found in the LICENSE file.
5
6
#ifndef LIB_JXL_IMAGE_H_
7
#define LIB_JXL_IMAGE_H_
8
9
// SIMD/multicore-friendly planar image representation with row accessors.
10
11
#include <inttypes.h>
12
#include <stddef.h>
13
#include <stdint.h>
14
#include <string.h>
15
16
#include <algorithm>
17
#include <sstream>
18
#include <utility>  // std::move
19
20
#include "lib/jxl/base/cache_aligned.h"
21
#include "lib/jxl/base/compiler_specific.h"
22
#include "lib/jxl/base/status.h"
23
#include "lib/jxl/common.h"
24
25
namespace jxl {
26
27
// Type-independent parts of Plane<> - reduces code duplication and facilitates
28
// moving member function implementations to cc file.
29
struct PlaneBase {
30
  PlaneBase()
31
      : xsize_(0),
32
        ysize_(0),
33
        orig_xsize_(0),
34
        orig_ysize_(0),
35
        bytes_per_row_(0),
36
2.98M
        bytes_(nullptr) {}
37
  PlaneBase(size_t xsize, size_t ysize, size_t sizeof_t);
38
39
  // Copy construction/assignment is forbidden to avoid inadvertent copies,
40
  // which can be very expensive. Use CopyImageTo() instead.
41
  PlaneBase(const PlaneBase& other) = delete;
42
  PlaneBase& operator=(const PlaneBase& other) = delete;
43
44
  // Move constructor (required for returning Image from function)
45
1.28M
  PlaneBase(PlaneBase&& other) noexcept = default;
46
47
  // Move assignment (required for std::vector)
48
7.72M
  PlaneBase& operator=(PlaneBase&& other) noexcept = default;
49
50
  void Swap(PlaneBase& other);
51
52
  // Useful for pre-allocating image with some padding for alignment purposes
53
  // and later reporting the actual valid dimensions. May also be used to
54
  // un-shrink the image. Caller is responsible for ensuring xsize/ysize are <=
55
  // the original dimensions.
56
920
  void ShrinkTo(const size_t xsize, const size_t ysize) {
57
920
    JXL_CHECK(xsize <= orig_xsize_);
58
920
    JXL_CHECK(ysize <= orig_ysize_);
59
920
    xsize_ = static_cast<uint32_t>(xsize);
60
920
    ysize_ = static_cast<uint32_t>(ysize);
61
    // NOTE: we can't recompute bytes_per_row for more compact storage and
62
    // better locality because that would invalidate the image contents.
63
920
  }
64
65
  // How many pixels.
66
63.3M
  JXL_INLINE size_t xsize() const { return xsize_; }
67
20.3M
  JXL_INLINE size_t ysize() const { return ysize_; }
68
69
  // NOTE: do not use this for copying rows - the valid xsize may be much less.
70
13.8M
  JXL_INLINE size_t bytes_per_row() const { return bytes_per_row_; }
71
72
  // Raw access to byte contents, for interfacing with other libraries.
73
  // Unsigned char instead of char to avoid surprises (sign extension).
74
12.1M
  JXL_INLINE uint8_t* bytes() {
75
12.1M
    void* p = bytes_.get();
76
12.1M
    return static_cast<uint8_t * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(p, 64));
77
12.1M
  }
78
1.69M
  JXL_INLINE const uint8_t* bytes() const {
79
1.69M
    const void* p = bytes_.get();
80
1.69M
    return static_cast<const uint8_t * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(p, 64));
81
1.69M
  }
82
83
 protected:
84
  // Returns pointer to the start of a row.
85
369M
  JXL_INLINE void* VoidRow(const size_t y) const {
86
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
87
    defined(THREAD_SANITIZER)
88
    if (y >= ysize_) {
89
      JXL_ABORT("Row(%" PRIu64 ") in (%u x %u) image\n", (uint64_t)y, xsize_,
90
                ysize_);
91
    }
92
#endif
93
94
369M
    void* row = bytes_.get() + y * bytes_per_row_;
95
369M
    return JXL_ASSUME_ALIGNED(row, 64);
96
369M
  }
97
98
  enum class Padding {
99
    // Allow Load(d, row + x) for x = 0; x < xsize(); x += Lanes(d). Default.
100
    kRoundUp,
101
    // Allow LoadU(d, row + x) for x = xsize() - 1. This requires an extra
102
    // vector to be initialized. If done by default, this would suppress
103
    // legitimate msan warnings. We therefore require users to explicitly call
104
    // InitializePadding before using unaligned loads (e.g. convolution).
105
    kUnaligned
106
  };
107
108
  // Initializes the minimum bytes required to suppress msan warnings from
109
  // legitimate (according to Padding mode) vector loads/stores on the right
110
  // border, where some lanes are uninitialized and assumed to be unused.
111
  void InitializePadding(size_t sizeof_t, Padding padding);
112
113
  // (Members are non-const to enable assignment during move-assignment.)
114
  uint32_t xsize_;  // In valid pixels, not including any padding.
115
  uint32_t ysize_;
116
  uint32_t orig_xsize_;
117
  uint32_t orig_ysize_;
118
  size_t bytes_per_row_;  // Includes padding.
119
  CacheAlignedUniquePtr bytes_;
120
};
121
122
// Single channel, aligned rows separated by padding. T must be POD.
123
//
124
// 'Single channel' (one 2D array per channel) simplifies vectorization
125
// (repeating the same operation on multiple adjacent components) without the
126
// complexity of a hybrid layout (8 R, 8 G, 8 B, ...). In particular, clients
127
// can easily iterate over all components in a row and Image requires no
128
// knowledge of the pixel format beyond the component type "T".
129
//
130
// 'Aligned' means each row is aligned to the L1 cache line size. This prevents
131
// false sharing between two threads operating on adjacent rows.
132
//
133
// 'Padding' is still relevant because vectors could potentially be larger than
134
// a cache line. By rounding up row sizes to the vector size, we allow
135
// reading/writing ALIGNED vectors whose first lane is a valid sample. This
136
// avoids needing a separate loop to handle remaining unaligned lanes.
137
//
138
// This image layout could also be achieved with a vector and a row accessor
139
// function, but a class wrapper with support for "deleter" allows wrapping
140
// existing memory allocated by clients without copying the pixels. It also
141
// provides convenient accessors for xsize/ysize, which shortens function
142
// argument lists. Supports move-construction so it can be stored in containers.
143
template <typename ComponentType>
144
class Plane : public PlaneBase {
145
 public:
146
  using T = ComponentType;
147
  static constexpr size_t kNumPlanes = 1;
148
149
2.98M
  Plane() = default;
jxl::Plane<int>::Plane()
Line
Count
Source
149
786k
  Plane() = default;
jxl::Plane<unsigned char>::Plane()
Line
Count
Source
149
33.1k
  Plane() = default;
jxl::Plane<signed char>::Plane()
Line
Count
Source
149
22.0k
  Plane() = default;
jxl::Plane<float>::Plane()
Line
Count
Source
149
2.12M
  Plane() = default;
jxl::Plane<hwy::float16_t>::Plane()
Line
Count
Source
149
1.23k
  Plane() = default;
jxl::Plane<unsigned int>::Plane()
Line
Count
Source
149
8.50k
  Plane() = default;
jxl::Plane<short>::Plane()
Line
Count
Source
149
4.56k
  Plane() = default;
Unexecuted instantiation: jxl::Plane<double>::Plane()
150
  Plane(const size_t xsize, const size_t ysize)
151
2.40M
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<int>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
1.12M
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<float>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
1.15M
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<hwy::float16_t>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
1.23k
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<unsigned int>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
8.50k
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<short>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
4.56k
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<unsigned char>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
72.8k
      : PlaneBase(xsize, ysize, sizeof(T)) {}
jxl::Plane<signed char>::Plane(unsigned long, unsigned long)
Line
Count
Source
151
48.3k
      : PlaneBase(xsize, ysize, sizeof(T)) {}
Unexecuted instantiation: jxl::Plane<double>::Plane(unsigned long, unsigned long)
152
153
  void InitializePaddingForUnalignedAccesses() {
154
    InitializePadding(sizeof(T), Padding::kUnaligned);
155
  }
156
157
311M
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
Unexecuted instantiation: jxl::Plane<double>::Row(unsigned long)
jxl::Plane<int>::Row(unsigned long)
Line
Count
Source
157
46.1M
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
jxl::Plane<unsigned char>::Row(unsigned long)
Line
Count
Source
157
913k
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
jxl::Plane<float>::Row(unsigned long)
Line
Count
Source
157
261M
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
jxl::Plane<hwy::float16_t>::Row(unsigned long)
Line
Count
Source
157
437k
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
jxl::Plane<unsigned int>::Row(unsigned long)
Line
Count
Source
157
2.04M
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
Unexecuted instantiation: jxl::Plane<short>::Row(unsigned long)
jxl::Plane<signed char>::Row(unsigned long)
Line
Count
Source
157
293k
  JXL_INLINE T* Row(const size_t y) { return static_cast<T*>(VoidRow(y)); }
158
159
  // Returns pointer to const (see above).
160
57.6M
  JXL_INLINE const T* Row(const size_t y) const {
161
57.6M
    return static_cast<const T*>(VoidRow(y));
162
57.6M
  }
Unexecuted instantiation: jxl::Plane<double>::Row(unsigned long) const
jxl::Plane<float>::Row(unsigned long) const
Line
Count
Source
160
8.37M
  JXL_INLINE const T* Row(const size_t y) const {
161
8.37M
    return static_cast<const T*>(VoidRow(y));
162
8.37M
  }
jxl::Plane<int>::Row(unsigned long) const
Line
Count
Source
160
49.2M
  JXL_INLINE const T* Row(const size_t y) const {
161
49.2M
    return static_cast<const T*>(VoidRow(y));
162
49.2M
  }
Unexecuted instantiation: jxl::Plane<unsigned char>::Row(unsigned long) const
163
164
  // Documents that the access is const.
165
8.18M
  JXL_INLINE const T* ConstRow(const size_t y) const {
166
8.18M
    return static_cast<const T*>(VoidRow(y));
167
8.18M
  }
jxl::Plane<unsigned char>::ConstRow(unsigned long) const
Line
Count
Source
165
1.26M
  JXL_INLINE const T* ConstRow(const size_t y) const {
166
1.26M
    return static_cast<const T*>(VoidRow(y));
167
1.26M
  }
jxl::Plane<float>::ConstRow(unsigned long) const
Line
Count
Source
165
4.66M
  JXL_INLINE const T* ConstRow(const size_t y) const {
166
4.66M
    return static_cast<const T*>(VoidRow(y));
167
4.66M
  }
jxl::Plane<int>::ConstRow(unsigned long) const
Line
Count
Source
165
1.86M
  JXL_INLINE const T* ConstRow(const size_t y) const {
166
1.86M
    return static_cast<const T*>(VoidRow(y));
167
1.86M
  }
jxl::Plane<signed char>::ConstRow(unsigned long) const
Line
Count
Source
165
389k
  JXL_INLINE const T* ConstRow(const size_t y) const {
166
389k
    return static_cast<const T*>(VoidRow(y));
167
389k
  }
Unexecuted instantiation: jxl::Plane<double>::ConstRow(unsigned long) const
168
169
  // Returns number of pixels (some of which are padding) per row. Useful for
170
  // computing other rows via pointer arithmetic. WARNING: this must
171
  // NOT be used to determine xsize.
172
3.25M
  JXL_INLINE intptr_t PixelsPerRow() const {
173
3.25M
    return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
174
3.25M
  }
jxl::Plane<int>::PixelsPerRow() const
Line
Count
Source
172
2.82M
  JXL_INLINE intptr_t PixelsPerRow() const {
173
2.82M
    return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
174
2.82M
  }
jxl::Plane<unsigned char>::PixelsPerRow() const
Line
Count
Source
172
28.0k
  JXL_INLINE intptr_t PixelsPerRow() const {
173
28.0k
    return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
174
28.0k
  }
jxl::Plane<float>::PixelsPerRow() const
Line
Count
Source
172
400k
  JXL_INLINE intptr_t PixelsPerRow() const {
173
400k
    return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
174
400k
  }
Unexecuted instantiation: jxl::Plane<short>::PixelsPerRow() const
175
};
176
177
using ImageSB = Plane<int8_t>;
178
using ImageB = Plane<uint8_t>;
179
using ImageS = Plane<int16_t>;  // signed integer or half-float
180
using ImageU = Plane<uint16_t>;
181
using ImageI = Plane<int32_t>;
182
using ImageF = Plane<float>;
183
using ImageD = Plane<double>;
184
185
// Also works for Image3 and mixed argument types.
186
template <class Image1, class Image2>
187
448k
bool SameSize(const Image1& image1, const Image2& image2) {
188
448k
  return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
189
448k
}
bool jxl::SameSize<jxl::RectT<unsigned long>, jxl::RectT<unsigned long> >(jxl::RectT<unsigned long> const&, jxl::RectT<unsigned long> const&)
Line
Count
Source
187
213k
bool SameSize(const Image1& image1, const Image2& image2) {
188
213k
  return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
189
213k
}
bool jxl::SameSize<jxl::Plane<int>, jxl::Plane<int> >(jxl::Plane<int> const&, jxl::Plane<int> const&)
Line
Count
Source
187
1.45k
bool SameSize(const Image1& image1, const Image2& image2) {
188
1.45k
  return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
189
1.45k
}
Unexecuted instantiation: bool jxl::SameSize<jxl::Plane<int>, jxl::Plane<float> >(jxl::Plane<int> const&, jxl::Plane<float> const&)
Unexecuted instantiation: bool jxl::SameSize<jxl::RectT<unsigned long>, jxl::Image3<float> >(jxl::RectT<unsigned long> const&, jxl::Image3<float> const&)
bool jxl::SameSize<jxl::RectT<unsigned long>, jxl::Plane<float> >(jxl::RectT<unsigned long> const&, jxl::Plane<float> const&)
Line
Count
Source
187
233k
bool SameSize(const Image1& image1, const Image2& image2) {
188
233k
  return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
189
233k
}
bool jxl::SameSize<jxl::Plane<float>, jxl::Plane<float> >(jxl::Plane<float> const&, jxl::Plane<float> const&)
Line
Count
Source
187
184
bool SameSize(const Image1& image1, const Image2& image2) {
188
184
  return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
189
184
}
bool jxl::SameSize<jxl::ImageBundle, jxl::Image3<float> >(jxl::ImageBundle const&, jxl::Image3<float> const&)
Line
Count
Source
187
92
bool SameSize(const Image1& image1, const Image2& image2) {
188
92
  return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize();
189
92
}
Unexecuted instantiation: bool jxl::SameSize<jxl::Image3<float>, jxl::Image3<float> >(jxl::Image3<float> const&, jxl::Image3<float> const&)
Unexecuted instantiation: bool jxl::SameSize<jxl::Plane<double>, jxl::Plane<double> >(jxl::Plane<double> const&, jxl::Plane<double> const&)
190
191
template <typename T>
192
class Image3;
193
194
// Rectangular region in image(s). Factoring this out of Image instead of
195
// shifting the pointer by x0/y0 allows this to apply to multiple images with
196
// different resolutions (e.g. color transform and quantization field).
197
// Can compare using SameSize(rect1, rect2).
198
template <typename T>
199
class RectT {
200
 public:
201
  // Most windows are xsize_max * ysize_max, except those on the borders where
202
  // begin + size_max > end.
203
  constexpr RectT(T xbegin, T ybegin, size_t xsize_max, size_t ysize_max,
204
                  T xend, T yend)
205
      : x0_(xbegin),
206
        y0_(ybegin),
207
        xsize_(ClampedSize(xbegin, xsize_max, xend)),
208
889k
        ysize_(ClampedSize(ybegin, ysize_max, yend)) {}
jxl::RectT<unsigned long>::RectT(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Line
Count
Source
208
855k
        ysize_(ClampedSize(ybegin, ysize_max, yend)) {}
jxl::RectT<long>::RectT(long, long, unsigned long, unsigned long, long, long)
Line
Count
Source
208
34.1k
        ysize_(ClampedSize(ybegin, ysize_max, yend)) {}
209
210
  // Construct with origin and known size (typically from another Rect).
211
  constexpr RectT(T xbegin, T ybegin, size_t xsize, size_t ysize)
212
3.76M
      : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {}
jxl::RectT<unsigned long>::RectT(unsigned long, unsigned long, unsigned long, unsigned long)
Line
Count
Source
212
2.88M
      : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {}
jxl::RectT<long>::RectT(long, long, unsigned long, unsigned long)
Line
Count
Source
212
874k
      : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {}
213
214
  // Construct a rect that covers a whole image/plane/ImageBundle etc.
215
  template <typename ImageT>
216
  explicit RectT(const ImageT& image)
217
544k
      : RectT(0, 0, image.xsize(), image.ysize()) {}
jxl::RectT<unsigned long>::RectT<jxl::Plane<float> >(jxl::Plane<float> const&)
Line
Count
Source
217
349k
      : RectT(0, 0, image.xsize(), image.ysize()) {}
jxl::RectT<unsigned long>::RectT<jxl::Image3<float> >(jxl::Image3<float> const&)
Line
Count
Source
217
736
      : RectT(0, 0, image.xsize(), image.ysize()) {}
jxl::RectT<unsigned long>::RectT<jxl::Plane<int> >(jxl::Plane<int> const&)
Line
Count
Source
217
194k
      : RectT(0, 0, image.xsize(), image.ysize()) {}
Unexecuted instantiation: jxl::RectT<unsigned long>::RectT<jxl::Plane<unsigned char> >(jxl::Plane<unsigned char> const&)
218
219
881k
  RectT() : RectT(0, 0, 0, 0) {}
220
221
  RectT(const RectT&) = default;
222
  RectT& operator=(const RectT&) = default;
223
224
  // Construct a subrect that resides in an image/plane/ImageBundle etc.
225
  template <typename ImageT>
226
129k
  RectT Crop(const ImageT& image) const {
227
129k
    return Intersection(RectT(image));
228
129k
  }
229
230
  // Construct a subrect that resides in the [0, ysize) x [0, xsize) region of
231
  // the current rect.
232
35.7k
  RectT Crop(size_t area_xsize, size_t area_ysize) const {
233
35.7k
    return Intersection(RectT(0, 0, area_xsize, area_ysize));
234
35.7k
  }
235
236
  // Returns a rect that only contains `num` lines with offset `y` from `y0()`.
237
5.24k
  RectT Lines(size_t y, size_t num) const {
238
5.24k
    JXL_DASSERT(y + num <= ysize_);
239
5.24k
    return RectT(x0_, y0_ + y, xsize_, num);
240
5.24k
  }
241
242
5.24k
  RectT Line(size_t y) const { return Lines(y, 1); }
243
244
198k
  JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const {
245
198k
    return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_,
246
198k
                 ysize_, std::min(x1(), other.x1()),
247
198k
                 std::min(y1(), other.y1()));
248
198k
  }
jxl::RectT<unsigned long>::Intersection(jxl::RectT<unsigned long> const&) const
Line
Count
Source
244
164k
  JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const {
245
164k
    return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_,
246
164k
                 ysize_, std::min(x1(), other.x1()),
247
164k
                 std::min(y1(), other.y1()));
248
164k
  }
jxl::RectT<long>::Intersection(jxl::RectT<long> const&) const
Line
Count
Source
244
34.1k
  JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const {
245
34.1k
    return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_,
246
34.1k
                 ysize_, std::min(x1(), other.x1()),
247
34.1k
                 std::min(y1(), other.y1()));
248
34.1k
  }
249
250
  JXL_MUST_USE_RESULT RectT Translate(int64_t x_offset,
251
347k
                                      int64_t y_offset) const {
252
347k
    return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_);
253
347k
  }
Unexecuted instantiation: jxl::RectT<unsigned long>::Translate(long, long) const
jxl::RectT<long>::Translate(long, long) const
Line
Count
Source
251
347k
                                      int64_t y_offset) const {
252
347k
    return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_);
253
347k
  }
254
255
  template <typename V>
256
22.7M
  V* Row(Plane<V>* image, size_t y) const {
257
22.7M
    JXL_DASSERT(y + y0_ >= 0);
258
22.7M
    return image->Row(y + y0_) + x0_;
259
22.7M
  }
unsigned char* jxl::RectT<unsigned long>::Row<unsigned char>(jxl::Plane<unsigned char>*, unsigned long) const
Line
Count
Source
256
536k
  V* Row(Plane<V>* image, size_t y) const {
257
536k
    JXL_DASSERT(y + y0_ >= 0);
258
536k
    return image->Row(y + y0_) + x0_;
259
536k
  }
float* jxl::RectT<unsigned long>::Row<float>(jxl::Plane<float>*, unsigned long) const
Line
Count
Source
256
14.2M
  V* Row(Plane<V>* image, size_t y) const {
257
14.2M
    JXL_DASSERT(y + y0_ >= 0);
258
14.2M
    return image->Row(y + y0_) + x0_;
259
14.2M
  }
int* jxl::RectT<unsigned long>::Row<int>(jxl::Plane<int>*, unsigned long) const
Line
Count
Source
256
7.69M
  V* Row(Plane<V>* image, size_t y) const {
257
7.69M
    JXL_DASSERT(y + y0_ >= 0);
258
7.69M
    return image->Row(y + y0_) + x0_;
259
7.69M
  }
signed char* jxl::RectT<unsigned long>::Row<signed char>(jxl::Plane<signed char>*, unsigned long) const
Line
Count
Source
256
73.2k
  V* Row(Plane<V>* image, size_t y) const {
257
73.2k
    JXL_DASSERT(y + y0_ >= 0);
258
73.2k
    return image->Row(y + y0_) + x0_;
259
73.2k
  }
float* jxl::RectT<long>::Row<float>(jxl::Plane<float>*, unsigned long) const
Line
Count
Source
256
156k
  V* Row(Plane<V>* image, size_t y) const {
257
156k
    JXL_DASSERT(y + y0_ >= 0);
258
156k
    return image->Row(y + y0_) + x0_;
259
156k
  }
260
261
  template <typename V>
262
  const V* Row(const Plane<V>* image, size_t y) const {
263
    JXL_DASSERT(y + y0_ >= 0);
264
    return image->Row(y + y0_) + x0_;
265
  }
266
267
  template <typename V>
268
860k
  V* PlaneRow(Image3<V>* image, const size_t c, size_t y) const {
269
860k
    JXL_DASSERT(y + y0_ >= 0);
270
860k
    return image->PlaneRow(c, y + y0_) + x0_;
271
860k
  }
272
273
  template <typename V>
274
6.29M
  const V* ConstRow(const Plane<V>& image, size_t y) const {
275
6.29M
    JXL_DASSERT(y + y0_ >= 0);
276
6.29M
    return image.ConstRow(y + y0_) + x0_;
277
6.29M
  }
float const* jxl::RectT<unsigned long>::ConstRow<float>(jxl::Plane<float> const&, unsigned long) const
Line
Count
Source
274
4.28M
  const V* ConstRow(const Plane<V>& image, size_t y) const {
275
4.28M
    JXL_DASSERT(y + y0_ >= 0);
276
4.28M
    return image.ConstRow(y + y0_) + x0_;
277
4.28M
  }
int const* jxl::RectT<unsigned long>::ConstRow<int>(jxl::Plane<int> const&, unsigned long) const
Line
Count
Source
274
1.76M
  const V* ConstRow(const Plane<V>& image, size_t y) const {
275
1.76M
    JXL_DASSERT(y + y0_ >= 0);
276
1.76M
    return image.ConstRow(y + y0_) + x0_;
277
1.76M
  }
unsigned char const* jxl::RectT<unsigned long>::ConstRow<unsigned char>(jxl::Plane<unsigned char> const&, unsigned long) const
Line
Count
Source
274
242k
  const V* ConstRow(const Plane<V>& image, size_t y) const {
275
242k
    JXL_DASSERT(y + y0_ >= 0);
276
242k
    return image.ConstRow(y + y0_) + x0_;
277
242k
  }
signed char const* jxl::RectT<unsigned long>::ConstRow<signed char>(jxl::Plane<signed char> const&, unsigned long) const
Line
Count
Source
274
368
  const V* ConstRow(const Plane<V>& image, size_t y) const {
275
368
    JXL_DASSERT(y + y0_ >= 0);
276
368
    return image.ConstRow(y + y0_) + x0_;
277
368
  }
278
279
  template <typename V>
280
583k
  const V* ConstPlaneRow(const Image3<V>& image, size_t c, size_t y) const {
281
583k
    JXL_DASSERT(y + y0_ >= 0);
282
583k
    return image.ConstPlaneRow(c, y + y0_) + x0_;
283
583k
  }
284
285
443k
  bool IsInside(const RectT& other) const {
286
443k
    return x0_ >= other.x0() && x1() <= other.x1() && y0_ >= other.y0() &&
287
443k
           y1() <= other.y1();
288
443k
  }
289
290
  // Returns true if this Rect fully resides in the given image. ImageT could be
291
  // Plane<T> or Image3<T>; however if ImageT is Rect, results are nonsensical.
292
  template <class ImageT>
293
403k
  bool IsInside(const ImageT& image) const {
294
403k
    return IsInside(RectT(image));
295
403k
  }
bool jxl::RectT<unsigned long>::IsInside<jxl::Plane<float> >(jxl::Plane<float> const&) const
Line
Count
Source
293
349k
  bool IsInside(const ImageT& image) const {
294
349k
    return IsInside(RectT(image));
295
349k
  }
bool jxl::RectT<unsigned long>::IsInside<jxl::Plane<int> >(jxl::Plane<int> const&) const
Line
Count
Source
293
53.8k
  bool IsInside(const ImageT& image) const {
294
53.8k
    return IsInside(RectT(image));
295
53.8k
  }
296
297
36.8M
  T x0() const { return x0_; }
jxl::RectT<unsigned long>::x0() const
Line
Count
Source
297
36.8M
  T x0() const { return x0_; }
jxl::RectT<long>::x0() const
Line
Count
Source
297
22.6k
  T x0() const { return x0_; }
298
37.1M
  T y0() const { return y0_; }
jxl::RectT<unsigned long>::y0() const
Line
Count
Source
298
37.1M
  T y0() const { return y0_; }
jxl::RectT<long>::y0() const
Line
Count
Source
298
11.5k
  T y0() const { return y0_; }
299
64.4M
  size_t xsize() const { return xsize_; }
jxl::RectT<unsigned long>::xsize() const
Line
Count
Source
299
64.4M
  size_t xsize() const { return xsize_; }
jxl::RectT<long>::xsize() const
Line
Count
Source
299
27.0k
  size_t xsize() const { return xsize_; }
300
45.9M
  size_t ysize() const { return ysize_; }
jxl::RectT<unsigned long>::ysize() const
Line
Count
Source
300
45.9M
  size_t ysize() const { return ysize_; }
jxl::RectT<long>::ysize() const
Line
Count
Source
300
22.7k
  size_t ysize() const { return ysize_; }
301
1.34M
  T x1() const { return x0_ + xsize_; }
jxl::RectT<unsigned long>::x1() const
Line
Count
Source
301
1.25M
  T x1() const { return x0_ + xsize_; }
jxl::RectT<long>::x1() const
Line
Count
Source
301
91.0k
  T x1() const { return x0_ + xsize_; }
302
1.29M
  T y1() const { return y0_ + ysize_; }
jxl::RectT<unsigned long>::y1() const
Line
Count
Source
302
1.21M
  T y1() const { return y0_ + ysize_; }
jxl::RectT<long>::y1() const
Line
Count
Source
302
79.8k
  T y1() const { return y0_ + ysize_; }
303
304
192k
  RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const {
305
192k
    return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx,
306
192k
                    ysize_ << shifty);
307
192k
  }
jxl::RectT<long>::ShiftLeft(unsigned long, unsigned long) const
Line
Count
Source
304
156k
  RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const {
305
156k
    return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx,
306
156k
                    ysize_ << shifty);
307
156k
  }
jxl::RectT<unsigned long>::ShiftLeft(unsigned long, unsigned long) const
Line
Count
Source
304
35.7k
  RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const {
305
35.7k
    return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx,
306
35.7k
                    ysize_ << shifty);
307
35.7k
  }
308
192k
  RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); }
jxl::RectT<long>::ShiftLeft(unsigned long) const
Line
Count
Source
308
156k
  RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); }
jxl::RectT<unsigned long>::ShiftLeft(unsigned long) const
Line
Count
Source
308
35.7k
  RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); }
309
310
  // Requires x0(), y0() to be multiples of 1<<shiftx, 1<<shifty.
311
375k
  RectT<T> CeilShiftRight(size_t shiftx, size_t shifty) const {
312
375k
    JXL_ASSERT(x0_ % (1 << shiftx) == 0);
313
375k
    JXL_ASSERT(y0_ % (1 << shifty) == 0);
314
375k
    return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty),
315
375k
                    DivCeil(xsize_, T{1} << shiftx),
316
375k
                    DivCeil(ysize_, T{1} << shifty));
317
375k
  }
jxl::RectT<long>::CeilShiftRight(unsigned long, unsigned long) const
Line
Count
Source
311
156k
  RectT<T> CeilShiftRight(size_t shiftx, size_t shifty) const {
312
156k
    JXL_ASSERT(x0_ % (1 << shiftx) == 0);
313
156k
    JXL_ASSERT(y0_ % (1 << shifty) == 0);
314
156k
    return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty),
315
156k
                    DivCeil(xsize_, T{1} << shiftx),
316
156k
                    DivCeil(ysize_, T{1} << shifty));
317
156k
  }
jxl::RectT<unsigned long>::CeilShiftRight(unsigned long, unsigned long) const
Line
Count
Source
311
218k
  RectT<T> CeilShiftRight(size_t shiftx, size_t shifty) const {
312
218k
    JXL_ASSERT(x0_ % (1 << shiftx) == 0);
313
218k
    JXL_ASSERT(y0_ % (1 << shifty) == 0);
314
218k
    return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty),
315
218k
                    DivCeil(xsize_, T{1} << shiftx),
316
218k
                    DivCeil(ysize_, T{1} << shifty));
317
218k
  }
318
375k
  RectT<T> CeilShiftRight(std::pair<size_t, size_t> shift) const {
319
375k
    return CeilShiftRight(shift.first, shift.second);
320
375k
  }
jxl::RectT<long>::CeilShiftRight(std::__1::pair<unsigned long, unsigned long>) const
Line
Count
Source
318
156k
  RectT<T> CeilShiftRight(std::pair<size_t, size_t> shift) const {
319
156k
    return CeilShiftRight(shift.first, shift.second);
320
156k
  }
jxl::RectT<unsigned long>::CeilShiftRight(std::__1::pair<unsigned long, unsigned long>) const
Line
Count
Source
318
218k
  RectT<T> CeilShiftRight(std::pair<size_t, size_t> shift) const {
319
218k
    return CeilShiftRight(shift.first, shift.second);
320
218k
  }
321
  RectT<T> CeilShiftRight(size_t shift) const {
322
    return CeilShiftRight(shift, shift);
323
  }
324
325
  template <typename U>
326
156k
  RectT<U> As() const {
327
156k
    return RectT<U>(U(x0_), U(y0_), U(xsize_), U(ysize_));
328
156k
  }
329
330
 private:
331
  // Returns size_max, or whatever is left in [begin, end).
332
1.77M
  static constexpr size_t ClampedSize(T begin, size_t size_max, T end) {
333
1.77M
    return (static_cast<T>(begin + size_max) <= end)
334
1.77M
               ? size_max
335
1.77M
               : (end > begin ? end - begin : 0);
336
1.77M
  }
jxl::RectT<unsigned long>::ClampedSize(unsigned long, unsigned long, unsigned long)
Line
Count
Source
332
1.71M
  static constexpr size_t ClampedSize(T begin, size_t size_max, T end) {
333
1.71M
    return (static_cast<T>(begin + size_max) <= end)
334
1.71M
               ? size_max
335
1.71M
               : (end > begin ? end - begin : 0);
336
1.71M
  }
jxl::RectT<long>::ClampedSize(long, unsigned long, long)
Line
Count
Source
332
68.3k
  static constexpr size_t ClampedSize(T begin, size_t size_max, T end) {
333
68.3k
    return (static_cast<T>(begin + size_max) <= end)
334
68.3k
               ? size_max
335
68.3k
               : (end > begin ? end - begin : 0);
336
68.3k
  }
337
338
  T x0_;
339
  T y0_;
340
341
  size_t xsize_;
342
  size_t ysize_;
343
};
344
345
template <typename T>
346
0
std::string Description(RectT<T> r) {
347
0
  std::ostringstream os;
348
0
  os << "[" << r.x0() << ".." << r.x1() << ")x"
349
0
     << "[" << r.y0() << ".." << r.y1() << ")";
350
0
  return os.str();
351
0
}
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > jxl::Description<unsigned long>(jxl::RectT<unsigned long>)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > jxl::Description<long>(jxl::RectT<long>)
352
353
using Rect = RectT<size_t>;
354
355
// Currently, we abuse Image to either refer to an image that owns its storage
356
// or one that doesn't. In similar vein, we abuse Image* function parameters to
357
// either mean "assign to me" or "fill the provided image with data".
358
// Hopefully, the "assign to me" meaning will go away and most images in the
359
// codebase will not be backed by own storage. When this happens we can redesign
360
// Image to be a non-storage-holding view class and introduce BackedImage in
361
// those places that actually need it.
362
363
// NOTE: we can't use Image as a view because invariants are violated
364
// (alignment and the presence of padding before/after each "row").
365
366
// A bundle of 3 same-sized images. Typically constructed by moving from three
367
// rvalue references to Image. To overwrite an existing Image3 using
368
// single-channel producers, we also need access to Image*. Constructing
369
// temporary non-owning Image pointing to one plane of an existing Image3 risks
370
// dangling references, especially if the wrapper is moved. Therefore, we
371
// store an array of Image (which are compact enough that size is not a concern)
372
// and provide Plane+Row accessors.
373
template <typename ComponentType>
374
class Image3 {
375
 public:
376
  using T = ComponentType;
377
  using PlaneT = jxl::Plane<T>;
378
  static constexpr size_t kNumPlanes = 3;
379
380
499k
  Image3() : planes_{PlaneT(), PlaneT(), PlaneT()} {}
jxl::Image3<float>::Image3()
Line
Count
Source
380
240k
  Image3() : planes_{PlaneT(), PlaneT(), PlaneT()} {}
jxl::Image3<int>::Image3()
Line
Count
Source
380
257k
  Image3() : planes_{PlaneT(), PlaneT(), PlaneT()} {}
jxl::Image3<short>::Image3()
Line
Count
Source
380
1.52k
  Image3() : planes_{PlaneT(), PlaneT(), PlaneT()} {}
381
382
  Image3(const size_t xsize, const size_t ysize)
383
      : planes_{PlaneT(xsize, ysize), PlaneT(xsize, ysize),
384
68.8k
                PlaneT(xsize, ysize)} {}
jxl::Image3<int>::Image3(unsigned long, unsigned long)
Line
Count
Source
384
13.8k
                PlaneT(xsize, ysize)} {}
jxl::Image3<float>::Image3(unsigned long, unsigned long)
Line
Count
Source
384
53.4k
                PlaneT(xsize, ysize)} {}
jxl::Image3<short>::Image3(unsigned long, unsigned long)
Line
Count
Source
384
1.52k
                PlaneT(xsize, ysize)} {}
Unexecuted instantiation: jxl::Image3<unsigned char>::Image3(unsigned long, unsigned long)
385
386
92
  Image3(Image3&& other) noexcept {
387
368
    for (size_t i = 0; i < kNumPlanes; i++) {
388
276
      planes_[i] = std::move(other.planes_[i]);
389
276
    }
390
92
  }
Unexecuted instantiation: jxl::Image3<int>::Image3(jxl::Image3<int>&&)
jxl::Image3<float>::Image3(jxl::Image3<float>&&)
Line
Count
Source
386
92
  Image3(Image3&& other) noexcept {
387
368
    for (size_t i = 0; i < kNumPlanes; i++) {
388
276
      planes_[i] = std::move(other.planes_[i]);
389
276
    }
390
92
  }
391
392
0
  Image3(PlaneT&& plane0, PlaneT&& plane1, PlaneT&& plane2) {
393
0
    JXL_CHECK(SameSize(plane0, plane1));
394
0
    JXL_CHECK(SameSize(plane0, plane2));
395
0
    planes_[0] = std::move(plane0);
396
0
    planes_[1] = std::move(plane1);
397
0
    planes_[2] = std::move(plane2);
398
0
  }
399
400
  // Copy construction/assignment is forbidden to avoid inadvertent copies,
401
  // which can be very expensive. Use CopyImageTo instead.
402
  Image3(const Image3& other) = delete;
403
  Image3& operator=(const Image3& other) = delete;
404
405
173k
  Image3& operator=(Image3&& other) noexcept {
406
694k
    for (size_t i = 0; i < kNumPlanes; i++) {
407
520k
      planes_[i] = std::move(other.planes_[i]);
408
520k
    }
409
173k
    return *this;
410
173k
  }
jxl::Image3<int>::operator=(jxl::Image3<int>&&)
Line
Count
Source
405
13.8k
  Image3& operator=(Image3&& other) noexcept {
406
55.4k
    for (size_t i = 0; i < kNumPlanes; i++) {
407
41.5k
      planes_[i] = std::move(other.planes_[i]);
408
41.5k
    }
409
13.8k
    return *this;
410
13.8k
  }
jxl::Image3<float>::operator=(jxl::Image3<float>&&)
Line
Count
Source
405
158k
  Image3& operator=(Image3&& other) noexcept {
406
632k
    for (size_t i = 0; i < kNumPlanes; i++) {
407
474k
      planes_[i] = std::move(other.planes_[i]);
408
474k
    }
409
158k
    return *this;
410
158k
  }
jxl::Image3<short>::operator=(jxl::Image3<short>&&)
Line
Count
Source
405
1.52k
  Image3& operator=(Image3&& other) noexcept {
406
6.08k
    for (size_t i = 0; i < kNumPlanes; i++) {
407
4.56k
      planes_[i] = std::move(other.planes_[i]);
408
4.56k
    }
409
1.52k
    return *this;
410
1.52k
  }
411
412
  // Returns row pointer; usage: PlaneRow(idx_plane, y)[x] = val.
413
12.1M
  JXL_INLINE T* PlaneRow(const size_t c, const size_t y) {
414
    // Custom implementation instead of calling planes_[c].Row ensures only a
415
    // single multiplication is needed for PlaneRow(0..2, y).
416
12.1M
    PlaneRowBoundsCheck(c, y);
417
12.1M
    const size_t row_offset = y * planes_[0].bytes_per_row();
418
12.1M
    void* row = planes_[c].bytes() + row_offset;
419
12.1M
    return static_cast<T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
420
12.1M
  }
jxl::Image3<int>::PlaneRow(unsigned long, unsigned long)
Line
Count
Source
413
583k
  JXL_INLINE T* PlaneRow(const size_t c, const size_t y) {
414
    // Custom implementation instead of calling planes_[c].Row ensures only a
415
    // single multiplication is needed for PlaneRow(0..2, y).
416
583k
    PlaneRowBoundsCheck(c, y);
417
583k
    const size_t row_offset = y * planes_[0].bytes_per_row();
418
583k
    void* row = planes_[c].bytes() + row_offset;
419
583k
    return static_cast<T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
420
583k
  }
jxl::Image3<float>::PlaneRow(unsigned long, unsigned long)
Line
Count
Source
413
11.5M
  JXL_INLINE T* PlaneRow(const size_t c, const size_t y) {
414
    // Custom implementation instead of calling planes_[c].Row ensures only a
415
    // single multiplication is needed for PlaneRow(0..2, y).
416
11.5M
    PlaneRowBoundsCheck(c, y);
417
11.5M
    const size_t row_offset = y * planes_[0].bytes_per_row();
418
11.5M
    void* row = planes_[c].bytes() + row_offset;
419
11.5M
    return static_cast<T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
420
11.5M
  }
jxl::Image3<short>::PlaneRow(unsigned long, unsigned long)
Line
Count
Source
413
57
  JXL_INLINE T* PlaneRow(const size_t c, const size_t y) {
414
    // Custom implementation instead of calling planes_[c].Row ensures only a
415
    // single multiplication is needed for PlaneRow(0..2, y).
416
57
    PlaneRowBoundsCheck(c, y);
417
57
    const size_t row_offset = y * planes_[0].bytes_per_row();
418
57
    void* row = planes_[c].bytes() + row_offset;
419
57
    return static_cast<T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
420
57
  }
Unexecuted instantiation: jxl::Image3<unsigned char>::PlaneRow(unsigned long, unsigned long)
421
422
  // Returns const row pointer; usage: val = PlaneRow(idx_plane, y)[x].
423
1.69M
  JXL_INLINE const T* PlaneRow(const size_t c, const size_t y) const {
424
1.69M
    PlaneRowBoundsCheck(c, y);
425
1.69M
    const size_t row_offset = y * planes_[0].bytes_per_row();
426
1.69M
    const void* row = planes_[c].bytes() + row_offset;
427
1.69M
    return static_cast<const T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
428
1.69M
  }
jxl::Image3<int>::PlaneRow(unsigned long, unsigned long) const
Line
Count
Source
423
542k
  JXL_INLINE const T* PlaneRow(const size_t c, const size_t y) const {
424
542k
    PlaneRowBoundsCheck(c, y);
425
542k
    const size_t row_offset = y * planes_[0].bytes_per_row();
426
542k
    const void* row = planes_[c].bytes() + row_offset;
427
542k
    return static_cast<const T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
428
542k
  }
jxl::Image3<float>::PlaneRow(unsigned long, unsigned long) const
Line
Count
Source
423
1.15M
  JXL_INLINE const T* PlaneRow(const size_t c, const size_t y) const {
424
1.15M
    PlaneRowBoundsCheck(c, y);
425
1.15M
    const size_t row_offset = y * planes_[0].bytes_per_row();
426
1.15M
    const void* row = planes_[c].bytes() + row_offset;
427
1.15M
    return static_cast<const T * JXL_RESTRICT>(JXL_ASSUME_ALIGNED(row, 64));
428
1.15M
  }
Unexecuted instantiation: jxl::Image3<short>::PlaneRow(unsigned long, unsigned long) const
429
430
  // Returns const row pointer, even if called from a non-const Image3.
431
1.68M
  JXL_INLINE const T* ConstPlaneRow(const size_t c, const size_t y) const {
432
1.68M
    PlaneRowBoundsCheck(c, y);
433
1.68M
    return PlaneRow(c, y);
434
1.68M
  }
jxl::Image3<float>::ConstPlaneRow(unsigned long, unsigned long) const
Line
Count
Source
431
1.14M
  JXL_INLINE const T* ConstPlaneRow(const size_t c, const size_t y) const {
432
1.14M
    PlaneRowBoundsCheck(c, y);
433
1.14M
    return PlaneRow(c, y);
434
1.14M
  }
jxl::Image3<int>::ConstPlaneRow(unsigned long, unsigned long) const
Line
Count
Source
431
542k
  JXL_INLINE const T* ConstPlaneRow(const size_t c, const size_t y) const {
432
542k
    PlaneRowBoundsCheck(c, y);
433
542k
    return PlaneRow(c, y);
434
542k
  }
435
436
108k
  JXL_INLINE const PlaneT& Plane(size_t idx) const { return planes_[idx]; }
jxl::Image3<float>::Plane(unsigned long) const
Line
Count
Source
436
108k
  JXL_INLINE const PlaneT& Plane(size_t idx) const { return planes_[idx]; }
Unexecuted instantiation: jxl::Image3<unsigned char>::Plane(unsigned long) const
437
438
3.07k
  JXL_INLINE PlaneT& Plane(size_t idx) { return planes_[idx]; }
Unexecuted instantiation: jxl::Image3<int>::Plane(unsigned long)
jxl::Image3<float>::Plane(unsigned long)
Line
Count
Source
438
3.07k
  JXL_INLINE PlaneT& Plane(size_t idx) { return planes_[idx]; }
Unexecuted instantiation: jxl::Image3<short>::Plane(unsigned long)
439
440
1.59k
  void Swap(Image3& other) {
441
6.39k
    for (size_t c = 0; c < 3; ++c) {
442
4.79k
      other.planes_[c].Swap(planes_[c]);
443
4.79k
    }
444
1.59k
  }
445
446
  // Useful for pre-allocating image with some padding for alignment purposes
447
  // and later reporting the actual valid dimensions. May also be used to
448
  // un-shrink the image. Caller is responsible for ensuring xsize/ysize are <=
449
  // the original dimensions.
450
276
  void ShrinkTo(const size_t xsize, const size_t ysize) {
451
828
    for (PlaneT& plane : planes_) {
452
828
      plane.ShrinkTo(xsize, ysize);
453
828
    }
454
276
  }
455
456
  // Sizes of all three images are guaranteed to be equal.
457
14.7M
  JXL_INLINE size_t xsize() const { return planes_[0].xsize(); }
jxl::Image3<int>::xsize() const
Line
Count
Source
457
14.8k
  JXL_INLINE size_t xsize() const { return planes_[0].xsize(); }
jxl::Image3<float>::xsize() const
Line
Count
Source
457
14.7M
  JXL_INLINE size_t xsize() const { return planes_[0].xsize(); }
jxl::Image3<short>::xsize() const
Line
Count
Source
457
12.2k
  JXL_INLINE size_t xsize() const { return planes_[0].xsize(); }
Unexecuted instantiation: jxl::Image3<unsigned char>::xsize() const
458
1.41M
  JXL_INLINE size_t ysize() const { return planes_[0].ysize(); }
jxl::Image3<int>::ysize() const
Line
Count
Source
458
56
  JXL_INLINE size_t ysize() const { return planes_[0].ysize(); }
jxl::Image3<float>::ysize() const
Line
Count
Source
458
1.41M
  JXL_INLINE size_t ysize() const { return planes_[0].ysize(); }
jxl::Image3<short>::ysize() const
Line
Count
Source
458
59
  JXL_INLINE size_t ysize() const { return planes_[0].ysize(); }
Unexecuted instantiation: jxl::Image3<unsigned char>::ysize() const
459
  // Returns offset [bytes] from one row to the next row of the same plane.
460
  // WARNING: this must NOT be used to determine xsize, nor for copying rows -
461
  // the valid xsize may be much less.
462
  JXL_INLINE size_t bytes_per_row() const { return planes_[0].bytes_per_row(); }
463
  // Returns number of pixels (some of which are padding) per row. Useful for
464
  // computing other rows via pointer arithmetic. WARNING: this must NOT be used
465
  // to determine xsize.
466
40.9k
  JXL_INLINE intptr_t PixelsPerRow() const { return planes_[0].PixelsPerRow(); }
jxl::Image3<int>::PixelsPerRow() const
Line
Count
Source
466
26.8k
  JXL_INLINE intptr_t PixelsPerRow() const { return planes_[0].PixelsPerRow(); }
Unexecuted instantiation: jxl::Image3<short>::PixelsPerRow() const
jxl::Image3<float>::PixelsPerRow() const
Line
Count
Source
466
14.0k
  JXL_INLINE intptr_t PixelsPerRow() const { return planes_[0].PixelsPerRow(); }
467
468
 private:
469
15.5M
  void PlaneRowBoundsCheck(const size_t c, const size_t y) const {
470
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
471
    defined(THREAD_SANITIZER)
472
    if (c >= kNumPlanes || y >= ysize()) {
473
      JXL_ABORT("PlaneRow(%" PRIu64 ", %" PRIu64 ") in (%" PRIu64 " x %" PRIu64
474
                ") image\n",
475
                static_cast<uint64_t>(c), static_cast<uint64_t>(y),
476
                static_cast<uint64_t>(xsize()), static_cast<uint64_t>(ysize()));
477
    }
478
#endif
479
15.5M
  }
jxl::Image3<int>::PlaneRowBoundsCheck(unsigned long, unsigned long) const
Line
Count
Source
469
1.66M
  void PlaneRowBoundsCheck(const size_t c, const size_t y) const {
470
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
471
    defined(THREAD_SANITIZER)
472
    if (c >= kNumPlanes || y >= ysize()) {
473
      JXL_ABORT("PlaneRow(%" PRIu64 ", %" PRIu64 ") in (%" PRIu64 " x %" PRIu64
474
                ") image\n",
475
                static_cast<uint64_t>(c), static_cast<uint64_t>(y),
476
                static_cast<uint64_t>(xsize()), static_cast<uint64_t>(ysize()));
477
    }
478
#endif
479
1.66M
  }
jxl::Image3<float>::PlaneRowBoundsCheck(unsigned long, unsigned long) const
Line
Count
Source
469
13.8M
  void PlaneRowBoundsCheck(const size_t c, const size_t y) const {
470
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
471
    defined(THREAD_SANITIZER)
472
    if (c >= kNumPlanes || y >= ysize()) {
473
      JXL_ABORT("PlaneRow(%" PRIu64 ", %" PRIu64 ") in (%" PRIu64 " x %" PRIu64
474
                ") image\n",
475
                static_cast<uint64_t>(c), static_cast<uint64_t>(y),
476
                static_cast<uint64_t>(xsize()), static_cast<uint64_t>(ysize()));
477
    }
478
#endif
479
13.8M
  }
jxl::Image3<short>::PlaneRowBoundsCheck(unsigned long, unsigned long) const
Line
Count
Source
469
57
  void PlaneRowBoundsCheck(const size_t c, const size_t y) const {
470
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
471
    defined(THREAD_SANITIZER)
472
    if (c >= kNumPlanes || y >= ysize()) {
473
      JXL_ABORT("PlaneRow(%" PRIu64 ", %" PRIu64 ") in (%" PRIu64 " x %" PRIu64
474
                ") image\n",
475
                static_cast<uint64_t>(c), static_cast<uint64_t>(y),
476
                static_cast<uint64_t>(xsize()), static_cast<uint64_t>(ysize()));
477
    }
478
#endif
479
57
  }
Unexecuted instantiation: jxl::Image3<unsigned char>::PlaneRowBoundsCheck(unsigned long, unsigned long) const
480
481
 private:
482
  PlaneT planes_[kNumPlanes];
483
};
484
485
using Image3B = Image3<uint8_t>;
486
using Image3S = Image3<int16_t>;
487
using Image3U = Image3<uint16_t>;
488
using Image3I = Image3<int32_t>;
489
using Image3F = Image3<float>;
490
using Image3D = Image3<double>;
491
492
}  // namespace jxl
493
494
#endif  // LIB_JXL_IMAGE_H_