/src/libjxl/lib/jxl/image_ops.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_OPS_H_ |
7 | | #define LIB_JXL_IMAGE_OPS_H_ |
8 | | |
9 | | // Operations on images. |
10 | | |
11 | | #include <jxl/memory_manager.h> |
12 | | |
13 | | #include <algorithm> |
14 | | #include <cstddef> |
15 | | #include <cstdint> |
16 | | #include <limits> |
17 | | |
18 | | #include "lib/jxl/base/compiler_specific.h" |
19 | | #include "lib/jxl/base/rect.h" |
20 | | #include "lib/jxl/base/status.h" |
21 | | #include "lib/jxl/frame_dimensions.h" |
22 | | #include "lib/jxl/image.h" |
23 | | |
24 | | namespace jxl { |
25 | | |
26 | | // Works for mixed image-like argument types. |
27 | | template <class Image1, class Image2> |
28 | 461k | bool SameSize(const Image1& image1, const Image2& image2) { |
29 | 461k | return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize(); |
30 | 461k | } bool jxl::SameSize<jxl::RectT<unsigned long>, jxl::RectT<unsigned long> >(jxl::RectT<unsigned long> const&, jxl::RectT<unsigned long> const&) Line | Count | Source | 28 | 172k | bool SameSize(const Image1& image1, const Image2& image2) { | 29 | 172k | return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize(); | 30 | 172k | } |
Unexecuted instantiation: bool jxl::SameSize<jxl::Plane<float>, jxl::Plane<float> >(jxl::Plane<float> const&, jxl::Plane<float> const&) bool jxl::SameSize<jxl::Plane<int>, jxl::Plane<int> >(jxl::Plane<int> const&, jxl::Plane<int> const&) Line | Count | Source | 28 | 111 | bool SameSize(const Image1& image1, const Image2& image2) { | 29 | 111 | return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize(); | 30 | 111 | } |
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 | 28 | 288k | bool SameSize(const Image1& image1, const Image2& image2) { | 29 | 288k | return image1.xsize() == image2.xsize() && image1.ysize() == image2.ysize(); | 30 | 288k | } |
|
31 | | |
32 | | template <typename T> |
33 | 111 | void CopyImageTo(const Plane<T>& from, Plane<T>* JXL_RESTRICT to) { |
34 | 111 | JXL_ASSERT(SameSize(from, *to)); |
35 | 111 | if (from.ysize() == 0 || from.xsize() == 0) return; |
36 | 15.2k | for (size_t y = 0; y < from.ysize(); ++y) { |
37 | 15.1k | const T* JXL_RESTRICT row_from = from.ConstRow(y); |
38 | 15.1k | T* JXL_RESTRICT row_to = to->Row(y); |
39 | 15.1k | memcpy(row_to, row_from, from.xsize() * sizeof(T)); |
40 | 15.1k | } |
41 | 108 | } Unexecuted instantiation: void jxl::CopyImageTo<float>(jxl::Plane<float> const&, jxl::Plane<float>*) void jxl::CopyImageTo<int>(jxl::Plane<int> const&, jxl::Plane<int>*) Line | Count | Source | 33 | 111 | void CopyImageTo(const Plane<T>& from, Plane<T>* JXL_RESTRICT to) { | 34 | 111 | JXL_ASSERT(SameSize(from, *to)); | 35 | 111 | if (from.ysize() == 0 || from.xsize() == 0) return; | 36 | 15.2k | for (size_t y = 0; y < from.ysize(); ++y) { | 37 | 15.1k | const T* JXL_RESTRICT row_from = from.ConstRow(y); | 38 | 15.1k | T* JXL_RESTRICT row_to = to->Row(y); | 39 | 15.1k | memcpy(row_to, row_from, from.xsize() * sizeof(T)); | 40 | 15.1k | } | 41 | 108 | } |
|
42 | | |
43 | | // Copies `from:rect_from` to `to:rect_to`. |
44 | | template <typename T> |
45 | | void CopyImageTo(const Rect& rect_from, const Plane<T>& from, |
46 | 164k | const Rect& rect_to, Plane<T>* JXL_RESTRICT to) { |
47 | 164k | JXL_DASSERT(SameSize(rect_from, rect_to)); |
48 | 164k | JXL_DASSERT(rect_from.IsInside(from)); |
49 | 164k | JXL_DASSERT(rect_to.IsInside(*to)); |
50 | 164k | if (rect_from.xsize() == 0) return; |
51 | 3.88M | for (size_t y = 0; y < rect_from.ysize(); ++y) { |
52 | 3.73M | const T* JXL_RESTRICT row_from = rect_from.ConstRow(from, y); |
53 | 3.73M | T* JXL_RESTRICT row_to = rect_to.Row(to, y); |
54 | 3.73M | memcpy(row_to, row_from, rect_from.xsize() * sizeof(T)); |
55 | 3.73M | } |
56 | 149k | } void jxl::CopyImageTo<float>(jxl::RectT<unsigned long> const&, jxl::Plane<float> const&, jxl::RectT<unsigned long> const&, jxl::Plane<float>*) Line | Count | Source | 46 | 158k | const Rect& rect_to, Plane<T>* JXL_RESTRICT to) { | 47 | 158k | JXL_DASSERT(SameSize(rect_from, rect_to)); | 48 | 158k | JXL_DASSERT(rect_from.IsInside(from)); | 49 | 158k | JXL_DASSERT(rect_to.IsInside(*to)); | 50 | 158k | if (rect_from.xsize() == 0) return; | 51 | 3.64M | for (size_t y = 0; y < rect_from.ysize(); ++y) { | 52 | 3.49M | const T* JXL_RESTRICT row_from = rect_from.ConstRow(from, y); | 53 | 3.49M | T* JXL_RESTRICT row_to = rect_to.Row(to, y); | 54 | 3.49M | memcpy(row_to, row_from, rect_from.xsize() * sizeof(T)); | 55 | 3.49M | } | 56 | 144k | } |
void jxl::CopyImageTo<int>(jxl::RectT<unsigned long> const&, jxl::Plane<int> const&, jxl::RectT<unsigned long> const&, jxl::Plane<int>*) Line | Count | Source | 46 | 5.62k | const Rect& rect_to, Plane<T>* JXL_RESTRICT to) { | 47 | 5.62k | JXL_DASSERT(SameSize(rect_from, rect_to)); | 48 | 5.62k | JXL_DASSERT(rect_from.IsInside(from)); | 49 | 5.62k | JXL_DASSERT(rect_to.IsInside(*to)); | 50 | 5.62k | if (rect_from.xsize() == 0) return; | 51 | 242k | for (size_t y = 0; y < rect_from.ysize(); ++y) { | 52 | 236k | const T* JXL_RESTRICT row_from = rect_from.ConstRow(from, y); | 53 | 236k | T* JXL_RESTRICT row_to = rect_to.Row(to, y); | 54 | 236k | memcpy(row_to, row_from, rect_from.xsize() * sizeof(T)); | 55 | 236k | } | 56 | 5.62k | } |
|
57 | | |
58 | | // Copies `from:rect_from` to `to:rect_to`. |
59 | | template <typename T> |
60 | | void CopyImageTo(const Rect& rect_from, const Image3<T>& from, |
61 | 0 | const Rect& rect_to, Image3<T>* JXL_RESTRICT to) { |
62 | 0 | JXL_ASSERT(SameSize(rect_from, rect_to)); |
63 | 0 | for (size_t c = 0; c < 3; c++) { |
64 | 0 | CopyImageTo(rect_from, from.Plane(c), rect_to, &to->Plane(c)); |
65 | 0 | } |
66 | 0 | } |
67 | | |
68 | | template <typename T, typename U> |
69 | | void ConvertPlaneAndClamp(const Rect& rect_from, const Plane<T>& from, |
70 | 8.01k | const Rect& rect_to, Plane<U>* JXL_RESTRICT to) { |
71 | 8.01k | JXL_ASSERT(SameSize(rect_from, rect_to)); |
72 | 8.01k | using M = decltype(T() + U()); |
73 | 69.1k | for (size_t y = 0; y < rect_to.ysize(); ++y) { |
74 | 61.1k | const T* JXL_RESTRICT row_from = rect_from.ConstRow(from, y); |
75 | 61.1k | U* JXL_RESTRICT row_to = rect_to.Row(to, y); |
76 | 193k | for (size_t x = 0; x < rect_to.xsize(); ++x) { |
77 | 132k | row_to[x] = |
78 | 132k | std::min<M>(std::max<M>(row_from[x], std::numeric_limits<U>::min()), |
79 | 132k | std::numeric_limits<U>::max()); |
80 | 132k | } |
81 | 61.1k | } |
82 | 8.01k | } |
83 | | |
84 | | // Copies `from` to `to`. |
85 | | template <typename T> |
86 | 0 | void CopyImageTo(const T& from, T* JXL_RESTRICT to) { |
87 | 0 | return CopyImageTo(Rect(from), from, Rect(*to), to); |
88 | 0 | } |
89 | | |
90 | | // Copies `from:rect_from` to `to:rect_to`; also copies `padding` pixels of |
91 | | // border around `from:rect_from`, in all directions, whenever they are inside |
92 | | // the first image. |
93 | | template <typename T> |
94 | | void CopyImageToWithPadding(const Rect& from_rect, const T& from, |
95 | 0 | size_t padding, const Rect& to_rect, T* to) { |
96 | 0 | size_t xextra0 = std::min(padding, from_rect.x0()); |
97 | 0 | size_t xextra1 = |
98 | 0 | std::min(padding, from.xsize() - from_rect.x0() - from_rect.xsize()); |
99 | 0 | size_t yextra0 = std::min(padding, from_rect.y0()); |
100 | 0 | size_t yextra1 = |
101 | 0 | std::min(padding, from.ysize() - from_rect.y0() - from_rect.ysize()); |
102 | 0 | JXL_DASSERT(to_rect.x0() >= xextra0); |
103 | 0 | JXL_DASSERT(to_rect.y0() >= yextra0); |
104 | | |
105 | 0 | return CopyImageTo(Rect(from_rect.x0() - xextra0, from_rect.y0() - yextra0, |
106 | 0 | from_rect.xsize() + xextra0 + xextra1, |
107 | 0 | from_rect.ysize() + yextra0 + yextra1), |
108 | 0 | from, |
109 | 0 | Rect(to_rect.x0() - xextra0, to_rect.y0() - yextra0, |
110 | 0 | to_rect.xsize() + xextra0 + xextra1, |
111 | 0 | to_rect.ysize() + yextra0 + yextra1), |
112 | 0 | to); |
113 | 0 | } |
114 | | |
115 | | // Returns linear combination of two grayscale images. |
116 | | template <typename T> |
117 | | StatusOr<Plane<T>> LinComb(const T lambda1, const Plane<T>& image1, |
118 | | const T lambda2, const Plane<T>& image2) { |
119 | | const size_t xsize = image1.xsize(); |
120 | | const size_t ysize = image1.ysize(); |
121 | | JXL_CHECK(xsize == image2.xsize()); |
122 | | JXL_CHECK(ysize == image2.ysize()); |
123 | | JxlMemoryManager* memory_manager = image1.memory_manager(); |
124 | | JXL_ASSIGN_OR_RETURN(Plane<T> out, |
125 | | Plane<T>::Create(memory_manager, xsize, ysize)); |
126 | | for (size_t y = 0; y < ysize; ++y) { |
127 | | const T* const JXL_RESTRICT row1 = image1.Row(y); |
128 | | const T* const JXL_RESTRICT row2 = image2.Row(y); |
129 | | T* const JXL_RESTRICT row_out = out.Row(y); |
130 | | for (size_t x = 0; x < xsize; ++x) { |
131 | | row_out[x] = lambda1 * row1[x] + lambda2 * row2[x]; |
132 | | } |
133 | | } |
134 | | return out; |
135 | | } |
136 | | |
137 | | // Multiplies image by lambda in-place |
138 | | template <typename T> |
139 | | void ScaleImage(const T lambda, Plane<T>* image) { |
140 | | for (size_t y = 0; y < image->ysize(); ++y) { |
141 | | T* const JXL_RESTRICT row = image->Row(y); |
142 | | for (size_t x = 0; x < image->xsize(); ++x) { |
143 | | row[x] = lambda * row[x]; |
144 | | } |
145 | | } |
146 | | } |
147 | | |
148 | | // Multiplies image by lambda in-place |
149 | | template <typename T> |
150 | | void ScaleImage(const T lambda, Image3<T>* image) { |
151 | | for (size_t c = 0; c < 3; ++c) { |
152 | | ScaleImage(lambda, &image->Plane(c)); |
153 | | } |
154 | | } |
155 | | |
156 | | template <typename T> |
157 | 17.4k | void FillImage(const T value, Plane<T>* image) { |
158 | 821k | for (size_t y = 0; y < image->ysize(); ++y) { |
159 | 804k | T* const JXL_RESTRICT row = image->Row(y); |
160 | 62.2M | for (size_t x = 0; x < image->xsize(); ++x) { |
161 | 61.4M | row[x] = value; |
162 | 61.4M | } |
163 | 804k | } |
164 | 17.4k | } void jxl::FillImage<unsigned char>(unsigned char, jxl::Plane<unsigned char>*) Line | Count | Source | 157 | 3.83k | void FillImage(const T value, Plane<T>* image) { | 158 | 282k | for (size_t y = 0; y < image->ysize(); ++y) { | 159 | 279k | T* const JXL_RESTRICT row = image->Row(y); | 160 | 2.50M | for (size_t x = 0; x < image->xsize(); ++x) { | 161 | 2.22M | row[x] = value; | 162 | 2.22M | } | 163 | 279k | } | 164 | 3.83k | } |
Unexecuted instantiation: void jxl::FillImage<int>(int, jxl::Plane<int>*) void jxl::FillImage<float>(float, jxl::Plane<float>*) Line | Count | Source | 157 | 13.6k | void FillImage(const T value, Plane<T>* image) { | 158 | 538k | for (size_t y = 0; y < image->ysize(); ++y) { | 159 | 525k | T* const JXL_RESTRICT row = image->Row(y); | 160 | 59.7M | for (size_t x = 0; x < image->xsize(); ++x) { | 161 | 59.2M | row[x] = value; | 162 | 59.2M | } | 163 | 525k | } | 164 | 13.6k | } |
|
165 | | |
166 | | template <typename T> |
167 | 2.14M | void ZeroFillImage(Plane<T>* image) { |
168 | 2.14M | if (image->xsize() == 0) return; |
169 | 5.16M | for (size_t y = 0; y < image->ysize(); ++y) { |
170 | 4.86M | T* const JXL_RESTRICT row = image->Row(y); |
171 | 4.86M | memset(row, 0, image->xsize() * sizeof(T)); |
172 | 4.86M | } |
173 | 293k | } void jxl::ZeroFillImage<int>(jxl::Plane<int>*) Line | Count | Source | 167 | 2.06M | void ZeroFillImage(Plane<T>* image) { | 168 | 2.06M | if (image->xsize() == 0) return; | 169 | 4.82M | for (size_t y = 0; y < image->ysize(); ++y) { | 170 | 4.60M | T* const JXL_RESTRICT row = image->Row(y); | 171 | 4.60M | memset(row, 0, image->xsize() * sizeof(T)); | 172 | 4.60M | } | 173 | 217k | } |
Unexecuted instantiation: void jxl::ZeroFillImage<short>(jxl::Plane<short>*) void jxl::ZeroFillImage<unsigned char>(jxl::Plane<unsigned char>*) Line | Count | Source | 167 | 18 | void ZeroFillImage(Plane<T>* image) { | 168 | 18 | if (image->xsize() == 0) return; | 169 | 402 | for (size_t y = 0; y < image->ysize(); ++y) { | 170 | 384 | T* const JXL_RESTRICT row = image->Row(y); | 171 | 384 | memset(row, 0, image->xsize() * sizeof(T)); | 172 | 384 | } | 173 | 18 | } |
void jxl::ZeroFillImage<signed char>(jxl::Plane<signed char>*) Line | Count | Source | 167 | 75.8k | void ZeroFillImage(Plane<T>* image) { | 168 | 75.8k | if (image->xsize() == 0) return; | 169 | 338k | for (size_t y = 0; y < image->ysize(); ++y) { | 170 | 262k | T* const JXL_RESTRICT row = image->Row(y); | 171 | 262k | memset(row, 0, image->xsize() * sizeof(T)); | 172 | 262k | } | 173 | 75.8k | } |
|
174 | | |
175 | | // Mirrors out of bounds coordinates and returns valid coordinates unchanged. |
176 | | // We assume the radius (distance outside the image) is small compared to the |
177 | | // image size, otherwise this might not terminate. |
178 | | // The mirror is outside the last column (border pixel is also replicated). |
179 | 14.4M | static inline int64_t Mirror(int64_t x, const int64_t xsize) { |
180 | 14.4M | JXL_DASSERT(xsize != 0); |
181 | | |
182 | | // TODO(janwas): replace with branchless version |
183 | 30.8M | while (x < 0 || x >= xsize) { |
184 | 16.4M | if (x < 0) { |
185 | 8.26M | x = -x - 1; |
186 | 8.26M | } else { |
187 | 8.18M | x = 2 * xsize - 1 - x; |
188 | 8.18M | } |
189 | 16.4M | } |
190 | 14.4M | return x; |
191 | 14.4M | } Unexecuted instantiation: djxl_fuzzer.cc:jxl::Mirror(long, long) Unexecuted instantiation: decode.cc:jxl::Mirror(long, long) Unexecuted instantiation: entropy_coder.cc:jxl::Mirror(long, long) Unexecuted instantiation: image_metadata.cc:jxl::Mirror(long, long) Unexecuted instantiation: encoding.cc:jxl::Mirror(long, long) Unexecuted instantiation: modular_image.cc:jxl::Mirror(long, long) Unexecuted instantiation: transform.cc:jxl::Mirror(long, long) Unexecuted instantiation: quant_weights.cc:jxl::Mirror(long, long) Unexecuted instantiation: quantizer.cc:jxl::Mirror(long, long) Unexecuted instantiation: decode_to_jpeg.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_jpeg_data_writer.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_frame.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_group.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_modular.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_patch_dictionary.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_xyb.cc:jxl::Mirror(long, long) Unexecuted instantiation: epf.cc:jxl::Mirror(long, long) Unexecuted instantiation: palette.cc:jxl::Mirror(long, long) Unexecuted instantiation: rct.cc:jxl::Mirror(long, long) Unexecuted instantiation: squeeze.cc:jxl::Mirror(long, long) Unexecuted instantiation: passes_state.cc:jxl::Mirror(long, long) Unexecuted instantiation: simple_render_pipeline.cc:jxl::Mirror(long, long) Unexecuted instantiation: toc.cc:jxl::Mirror(long, long) Unexecuted instantiation: ac_strategy.cc:jxl::Mirror(long, long) Unexecuted instantiation: chroma_from_luma.cc:jxl::Mirror(long, long) Unexecuted instantiation: coeff_order.cc:jxl::Mirror(long, long) Unexecuted instantiation: dec_cache.cc:jxl::Mirror(long, long) low_memory_render_pipeline.cc:jxl::Mirror(long, long) Line | Count | Source | 179 | 14.4M | static inline int64_t Mirror(int64_t x, const int64_t xsize) { | 180 | 14.4M | JXL_DASSERT(xsize != 0); | 181 | | | 182 | | // TODO(janwas): replace with branchless version | 183 | 30.8M | while (x < 0 || x >= xsize) { | 184 | 16.4M | if (x < 0) { | 185 | 8.26M | x = -x - 1; | 186 | 8.26M | } else { | 187 | 8.18M | x = 2 * xsize - 1 - x; | 188 | 8.18M | } | 189 | 16.4M | } | 190 | 14.4M | return x; | 191 | 14.4M | } |
Unexecuted instantiation: stage_blending.cc:jxl::Mirror(long, long) Unexecuted instantiation: stage_epf.cc:jxl::Mirror(long, long) Unexecuted instantiation: stage_patches.cc:jxl::Mirror(long, long) Unexecuted instantiation: stage_write.cc:jxl::Mirror(long, long) Unexecuted instantiation: image_bundle.cc:jxl::Mirror(long, long) |
192 | | |
193 | | // Wrap modes for ensuring X/Y coordinates are in the valid range [0, size): |
194 | | |
195 | | // Mirrors (repeating the edge pixel once). Useful for convolutions. |
196 | | struct WrapMirror { |
197 | 0 | JXL_INLINE int64_t operator()(const int64_t coord, const int64_t size) const { |
198 | 0 | return Mirror(coord, size); |
199 | 0 | } |
200 | | }; |
201 | | |
202 | | // Returns the same coordinate: required for TFNode with Border(), or useful |
203 | | // when we know "coord" is already valid (e.g. interior of an image). |
204 | | struct WrapUnchanged { |
205 | 0 | JXL_INLINE int64_t operator()(const int64_t coord, int64_t /*size*/) const { |
206 | 0 | return coord; |
207 | 0 | } |
208 | | }; |
209 | | |
210 | | // Similar to Wrap* but for row pointers (reduces Row() multiplications). |
211 | | |
212 | | class WrapRowMirror { |
213 | | public: |
214 | | template <class ImageOrView> |
215 | | WrapRowMirror(const ImageOrView& image, size_t ysize) |
216 | | : first_row_(image.ConstRow(0)), last_row_(image.ConstRow(ysize - 1)) {} |
217 | | |
218 | | const float* operator()(const float* const JXL_RESTRICT row, |
219 | 0 | const int64_t stride) const { |
220 | 0 | if (row < first_row_) { |
221 | 0 | const int64_t num_before = first_row_ - row; |
222 | 0 | // Mirrored; one row before => row 0, two before = row 1, ... |
223 | 0 | return first_row_ + num_before - stride; |
224 | 0 | } |
225 | 0 | if (row > last_row_) { |
226 | 0 | const int64_t num_after = row - last_row_; |
227 | 0 | // Mirrored; one row after => last row, two after = last - 1, ... |
228 | 0 | return last_row_ - num_after + stride; |
229 | 0 | } |
230 | 0 | return row; |
231 | 0 | } |
232 | | |
233 | | private: |
234 | | const float* const JXL_RESTRICT first_row_; |
235 | | const float* const JXL_RESTRICT last_row_; |
236 | | }; |
237 | | |
238 | | struct WrapRowUnchanged { |
239 | | JXL_INLINE const float* operator()(const float* const JXL_RESTRICT row, |
240 | 0 | int64_t /*stride*/) const { |
241 | 0 | return row; |
242 | 0 | } |
243 | | }; |
244 | | |
245 | | // Computes the minimum and maximum pixel value. |
246 | | template <typename T> |
247 | | void ImageMinMax(const Plane<T>& image, T* const JXL_RESTRICT min, |
248 | | T* const JXL_RESTRICT max) { |
249 | | *min = std::numeric_limits<T>::max(); |
250 | | *max = std::numeric_limits<T>::lowest(); |
251 | | for (size_t y = 0; y < image.ysize(); ++y) { |
252 | | const T* const JXL_RESTRICT row = image.Row(y); |
253 | | for (size_t x = 0; x < image.xsize(); ++x) { |
254 | | *min = std::min(*min, row[x]); |
255 | | *max = std::max(*max, row[x]); |
256 | | } |
257 | | } |
258 | | } |
259 | | |
260 | | // Initializes all planes to the same "value". |
261 | | template <typename T> |
262 | | void FillImage(const T value, Image3<T>* image) { |
263 | | for (size_t c = 0; c < 3; ++c) { |
264 | | for (size_t y = 0; y < image->ysize(); ++y) { |
265 | | T* JXL_RESTRICT row = image->PlaneRow(c, y); |
266 | | for (size_t x = 0; x < image->xsize(); ++x) { |
267 | | row[x] = value; |
268 | | } |
269 | | } |
270 | | } |
271 | | } |
272 | | |
273 | | template <typename T> |
274 | 0 | void FillPlane(const T value, Plane<T>* image, Rect rect) { |
275 | 0 | for (size_t y = 0; y < rect.ysize(); ++y) { |
276 | 0 | T* JXL_RESTRICT row = rect.Row(image, y); |
277 | 0 | for (size_t x = 0; x < rect.xsize(); ++x) { |
278 | 0 | row[x] = value; |
279 | 0 | } |
280 | 0 | } |
281 | 0 | } |
282 | | |
283 | | template <typename T> |
284 | 46 | void ZeroFillImage(Image3<T>* image) { |
285 | 184 | for (size_t c = 0; c < 3; ++c) { |
286 | 276 | for (size_t y = 0; y < image->ysize(); ++y) { |
287 | 138 | T* JXL_RESTRICT row = image->PlaneRow(c, y); |
288 | 138 | if (image->xsize() != 0) memset(row, 0, image->xsize() * sizeof(T)); |
289 | 138 | } |
290 | 138 | } |
291 | 46 | } void jxl::ZeroFillImage<int>(jxl::Image3<int>*) Line | Count | Source | 284 | 20 | void ZeroFillImage(Image3<T>* image) { | 285 | 80 | for (size_t c = 0; c < 3; ++c) { | 286 | 120 | for (size_t y = 0; y < image->ysize(); ++y) { | 287 | 60 | T* JXL_RESTRICT row = image->PlaneRow(c, y); | 288 | 60 | if (image->xsize() != 0) memset(row, 0, image->xsize() * sizeof(T)); | 289 | 60 | } | 290 | 60 | } | 291 | 20 | } |
void jxl::ZeroFillImage<short>(jxl::Image3<short>*) Line | Count | Source | 284 | 26 | void ZeroFillImage(Image3<T>* image) { | 285 | 104 | for (size_t c = 0; c < 3; ++c) { | 286 | 156 | for (size_t y = 0; y < image->ysize(); ++y) { | 287 | 78 | T* JXL_RESTRICT row = image->PlaneRow(c, y); | 288 | 78 | if (image->xsize() != 0) memset(row, 0, image->xsize() * sizeof(T)); | 289 | 78 | } | 290 | 78 | } | 291 | 26 | } |
|
292 | | |
293 | | // Same as above, but operates in-place. Assumes that the `in` image was |
294 | | // allocated large enough. |
295 | | void PadImageToBlockMultipleInPlace(Image3F* JXL_RESTRICT in, |
296 | | size_t block_dim = kBlockDim); |
297 | | |
298 | | // Downsamples an image by a given factor. |
299 | | StatusOr<Image3F> DownsampleImage(const Image3F& opsin, size_t factor); |
300 | | StatusOr<ImageF> DownsampleImage(const ImageF& image, size_t factor); |
301 | | |
302 | | } // namespace jxl |
303 | | |
304 | | #endif // LIB_JXL_IMAGE_OPS_H_ |