Ocean
AdvancedFrameInterpolatorBilinearBase.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_BASE_H
9 #define META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_BASE_H
10 
12 #include "ocean/cv/SSE.h"
13 
15 #include "ocean/cv/CVUtilities.h"
16 
17 #include "ocean/math/Vector2.h"
18 
19 namespace Ocean
20 {
21 
22 namespace CV
23 {
24 
25 namespace Advanced
26 {
27 
28 /**
29  * This class implements several advanced bilinear frame interpolator functions based e.g., on template parameters.
30  * @ingroup cvadvanced
31  */
33 {
34  public:
35 
36  /**
37  * Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
38  * The center of a pixel is expected to be located at the top-left corner of a pixel.
39  * @param image The image in which the interpolated patch is located, must be valid
40  * @param width The width of the image, in pixel, with range [tPatchSize + 1, infinity)
41  * @param imagePaddingElements The number of padding elements at the end of each image row, in elements, with range [0, infinity)
42  * @param buffer The target buffer with `tChannels * tSize * tSize` elements, must be valid
43  * @param position The center position of the square patch in the image, with range [tPatchSize/2, width - tPatchSize/2 - 1)x[tPatchSize/2, height - tPatchSize/2 - 1) for PC_TOP_LEFT, [0.5 + tPatchSize/2, width - tPatchSize/2 - 0.5)x[0.5 + tPatchSize/2, height - tPatchSize/2 - 0.5) for PC_CENTER
44  * @tparam tChannels The number of frame channels, with range [1, infinity)
45  * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
46  * @tparam TScalar The scalar data type of the sub-pixel position
47  */
48  template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter = PC_TOP_LEFT, typename TScalar = Scalar>
49  static inline void interpolateSquarePatch8BitPerChannelTemplate(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position);
50 
51  /**
52  * Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
53  * The center of a pixel is expected to be located at the top-left corner of a pixel.
54  * @param image The image in which the interpolated patch is located, must be valid
55  * @param width The width of the image, in pixel, with range [patchWidth + 1, infinity)
56  * @param imagePaddingElements The number of padding elements at the end of each image row, in elements, with range [0, infinity)
57  * @param buffer The target buffer with `tChannels * tSize * tSize` elements, must be valid
58  * @param position The center position of the patch in the image, with range [patchWidth/2, width - patchWidth/2 - 1)x[patchHeight/2, height - patchHeight/2 - 1) for PC_TOP_LEFT, [0.5 + patchWidth/2, width - patchWidth/2 - 0.5)x[0.5 + patchHeight/2, height - patchHeight/2 - 0.5) for PC_CENTER
59  * @param patchWidth The width of the image patch in pixel, with range [1, infinity), must be odd
60  * @param patchHeight The height of the image patch in pixel, with range [1, infinity), must be odd
61  * @tparam tChannels The number of frame channels, with range [1, infinity)
62  * @tparam tPixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
63  * @tparam TScalar The scalar data type of the sub-pixel position
64  */
65  template <unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT, typename TScalar = Scalar>
66  static void interpolatePatch8BitPerChannel(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position, const unsigned int patchWidth, const unsigned int patchHeight);
67 
68  /**
69  * Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
70  * Pixels in the square region pointing outside the frame are mirrored back into the frame.
71  * @param frame The image in which the interpolated patch is located, must be valid
72  * @param width The width of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
73  * @param height The height of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
74  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
75  * @param buffer The target buffer with `tChannels * patchSize * patchSize` elements, must be valid
76  * @param position Center position of the square region in the source frame, with range [0, width)x[0, height)
77  * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
78  * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
79  */
80  template <unsigned int tChannels>
81  static void interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position, const unsigned int patchSize);
82 
83  /**
84  * Interpolates the content of a square region inside a given frame into a buffer with size of the square window.
85  * Pixels in the square region pointing outside the frame are mirrored back into the frame.
86  * @param frame The image in which the interpolated patch is located, must be valid
87  * @param width The width of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
88  * @param height The height of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
89  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
90  * @param buffer The target buffer with `tChannels * patchSize * patchSize` elements, must be valid
91  * @param position Center position of the square region in the source frame, with range [0, width)x[0, height)
92  * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
93  * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
94  */
95  template <unsigned int tChannels, unsigned int tPatchSize>
96  static void interpolateSquareMirroredBorderTemplate8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position);
97 
98  /**
99  * Interpolates the content of 2x2 pixels to one pixel.
100  * @param sourceTopLeft Top left position of the 2x2 pixels to interpolate, must be valid
101  * @param sourceBottomLeft Bottom left position of the 2x2 pixels to interpolate, must be valid
102  * @param target Position of the target pixel
103  * @param xFactor Horizontal interpolation factor with range [0, 128]
104  * @param yFactor Vertical interpolation factor with range [0, 128]
105  * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
106  */
107  template <unsigned int tChannels>
108  static inline void interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int xFactor, const unsigned int yFactor);
109 
110  /**
111  * Interpolates the content of 2x2 pixels to one pixel.
112  * @param sourceTopLeft Top left position of the 2x2 pixels to interpolate, must be valid
113  * @param sourceBottomLeft Bottom left position of the 2x2 pixels to interpolate, must be valid
114  * @param target Position of the target pixel
115  * @param tx_ty_ (128u - xFactor) * (128u - yFactor)
116  * @param txty_ xFactor * (128u - yFactor)
117  * @param tx_ty (128u - xFactor) * yFactor
118  * @param txty xFactor * yFactor
119  * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
120  */
121  template <unsigned int tChannels>
122  static inline void interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int tx_ty_, const unsigned int txty_, const unsigned int tx_ty, const unsigned int txty);
123 };
124 
125 template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter, typename TScalar>
126 inline void AdvancedFrameInterpolatorBilinearBase::interpolateSquarePatch8BitPerChannelTemplate(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position)
127 {
128  static_assert(tChannels >= 1u, "Invalid channel number!");
129  static_assert(tPatchSize % 2u == 1u, "The patch size must be odd!");
130 
131  ocean_assert(image != nullptr && buffer != nullptr);
132  ocean_assert(tPatchSize + 1u <= width);
133 
134  constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
135 
136  const unsigned int imageStrideElements = width * tChannels + imagePaddingElements;
137 
138  const VectorT2<TScalar> shiftedPosition = tPixelCenter == PC_TOP_LEFT ? position : position - VectorT2<TScalar>(TScalar(0.5), TScalar(0.5));
139 
140  ocean_assert(shiftedPosition.x() >= TScalar(tPatchSize_2) && shiftedPosition.y() >= TScalar(tPatchSize_2));
141  ocean_assert(shiftedPosition.x() < TScalar(width - tPatchSize_2 - 1u));
142 
143  const unsigned int left = (unsigned int)(shiftedPosition.x()) - tPatchSize_2;
144  const unsigned int top = (unsigned int)(shiftedPosition.y()) - tPatchSize_2;
145 
146  ocean_assert(left + tPatchSize < width);
147 
148  const TScalar tx = shiftedPosition.x() - TScalar(int(shiftedPosition.x()));
149  ocean_assert(tx >= TScalar(0) && tx <= TScalar(1));
150  const unsigned int factorRight = (unsigned int)(tx * TScalar(128) + TScalar(0.5));
151  const unsigned int factorLeft = 128u - factorRight;
152 
153  const TScalar ty = shiftedPosition.y() - TScalar(int(shiftedPosition.y()));
154  ocean_assert(ty >= 0 && ty <= 1);
155  const unsigned int factorBottom = (unsigned int)(ty * TScalar(128) + TScalar(0.5));
156  const unsigned int factorTop = 128u - factorBottom;
157 
158  const unsigned int factorTopLeft = factorLeft * factorTop;
159  const unsigned int factorTopRight = factorRight * factorTop;
160  const unsigned int factorBottomLeft = factorLeft * factorBottom;
161  const unsigned int factorBottomRight = factorRight * factorBottom;
162 
163  const uint8_t* imageTop = image + top * imageStrideElements + left * tChannels;
164  const uint8_t* imageBottom = imageTop + imageStrideElements;
165 
166  const uint8_t* const imageEnd = imageTop + imageStrideElements * tPatchSize;
167 
168  const unsigned int imageRowOffset = imageStrideElements - tChannels * tPatchSize;
169 
170  while (imageTop != imageEnd)
171  {
172  ocean_assert(imageTop < imageEnd);
173  ocean_assert((imageTop - image) % imageStrideElements == tChannels * left);
174 
175  const uint8_t* const imageEndRow = imageTop + tChannels * tPatchSize;
176 
177  while (imageTop != imageEndRow)
178  {
179  ocean_assert(imageTop < imageEnd);
180  ocean_assert(imageTop < imageEndRow);
181 
182  for (unsigned int n = 0u; n < tChannels; ++n)
183  {
184  *buffer++ = uint8_t((imageTop[n] * factorTopLeft + imageTop[n + tChannels] * factorTopRight + imageBottom[n] * factorBottomLeft + imageBottom[n + tChannels] * factorBottomRight + 8192u) / 16384u);
185  }
186 
187  imageTop += tChannels;
188  imageBottom += tChannels;
189  }
190 
191  imageTop += imageRowOffset;
192  imageBottom += imageRowOffset;
193  }
194 }
195 
196 template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
197 void AdvancedFrameInterpolatorBilinearBase::interpolatePatch8BitPerChannel(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position, const unsigned int patchWidth, const unsigned int patchHeight)
198 {
199  static_assert(tChannels >= 1u, "Invalid channel number!");
200 
201  ocean_assert(image != nullptr && buffer != nullptr);
202  ocean_assert(patchWidth + 1u <= width);
203 
204  const unsigned int patchWidth_2 = patchWidth / 2u;
205  const unsigned int patchHeight_2 = patchHeight / 2u;
206 
207  const unsigned int imageStrideElements = width * tChannels + imagePaddingElements;
208 
209  const VectorT2<TScalar> shiftedPosition = tPixelCenter == PC_TOP_LEFT ? position : position - VectorT2<TScalar>(TScalar(0.5), TScalar(0.5));
210 
211  ocean_assert(shiftedPosition.x() >= TScalar(patchWidth_2) && shiftedPosition.y() >= TScalar(patchHeight_2));
212  ocean_assert(shiftedPosition.x() < TScalar(width - patchWidth_2 - 1u));
213 
214  const unsigned int left = (unsigned int)(shiftedPosition.x()) - patchWidth_2;
215  const unsigned int top = (unsigned int)(shiftedPosition.y()) - patchHeight_2;
216 
217  ocean_assert(left + patchWidth < width);
218 
219  const TScalar tx = shiftedPosition.x() - TScalar(int(shiftedPosition.x()));
220  ocean_assert(tx >= TScalar(0) && tx <= TScalar(1));
221  const unsigned int factorRight = (unsigned int)(tx * TScalar(128) + TScalar(0.5));
222  const unsigned int factorLeft = 128u - factorRight;
223 
224  const TScalar ty = shiftedPosition.y() - TScalar(int(shiftedPosition.y()));
225  ocean_assert(ty >= 0 && ty <= 1);
226  const unsigned int factorBottom = (unsigned int)(ty * TScalar(128) + TScalar(0.5));
227  const unsigned int factorTop = 128u - factorBottom;
228 
229  const unsigned int factorTopLeft = factorLeft * factorTop;
230  const unsigned int factorTopRight = factorRight * factorTop;
231  const unsigned int factorBottomLeft = factorLeft * factorBottom;
232  const unsigned int factorBottomRight = factorRight * factorBottom;
233 
234  const uint8_t* imageTop = image + top * imageStrideElements + left * tChannels;
235  const uint8_t* imageBottom = imageTop + imageStrideElements;
236 
237  const uint8_t* const imageEnd = imageTop + imageStrideElements * patchHeight;
238 
239  const unsigned int imageRowOffset = imageStrideElements - tChannels * patchWidth;
240 
241  while (imageTop != imageEnd)
242  {
243  ocean_assert(imageTop < imageEnd);
244  ocean_assert((imageTop - image) % imageStrideElements == tChannels * left);
245 
246  const uint8_t* const imageEndRow = imageTop + tChannels * patchWidth;
247 
248  while (imageTop != imageEndRow)
249  {
250  ocean_assert(imageTop < imageEnd);
251  ocean_assert(imageTop < imageEndRow);
252 
253  for (unsigned int n = 0u; n < tChannels; ++n)
254  {
255  *buffer++ = uint8_t((imageTop[n] * factorTopLeft + imageTop[n + tChannels] * factorTopRight + imageBottom[n] * factorBottomLeft + imageBottom[n + tChannels] * factorBottomRight + 8192u) / 16384u);
256  }
257 
258  imageTop += tChannels;
259  imageBottom += tChannels;
260  }
261 
262  imageTop += imageRowOffset;
263  imageBottom += imageRowOffset;
264  }
265 }
266 
267 template <unsigned int tChannels>
268 void AdvancedFrameInterpolatorBilinearBase::interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position, const unsigned int patchSize)
269 {
270  ocean_assert(frame != nullptr && buffer != nullptr);
271  ocean_assert(patchSize >= 1u && patchSize % 2u == 1u);
272 
273  const unsigned int patchSize_2 = patchSize / 2u;
274 
275  ocean_assert(position.x() >= Scalar(0) && position.y() >= Scalar(0));
276  ocean_assert(position.x() < Scalar(width) && position.y() < Scalar(height));
277 
278  const int left = int(position.x()) - int(patchSize_2);
279  const int top = int(position.y()) - int(patchSize_2);
280 
281  const Scalar tx = position.x() - Scalar(patchSize_2) - Scalar(left);
282  ocean_assert(tx >= 0 && tx <= 1);
283  const unsigned int txi = (unsigned int)(tx * Scalar(128) + Scalar(0.5));
284  const unsigned int txi_ = 128u - txi;
285 
286  const Scalar ty = position.y() - Scalar(patchSize_2) - Scalar(top);
287  ocean_assert(ty >= 0 && ty <= 1);
288  const unsigned int tyi = (unsigned int)(ty * Scalar(128) + Scalar(0.5));
289  const unsigned int tyi_ = 128u - tyi;
290 
291  const unsigned int tx_y_ = txi_ * tyi_;
292  const unsigned int txy_ = txi * tyi_;
293  const unsigned int tx_y = txi_ * tyi;
294  const unsigned int txy = txi * tyi;
295 
296  const int frameStrideElements = int(width * tChannels + framePaddingElements);
297 
298  const uint8_t* frameTop = frame + top * frameStrideElements + left * int(tChannels);
299  const uint8_t* frameBottom = frameTop + frameStrideElements;
300 
301  for (unsigned int y = 0u; y < patchSize; ++y)
302  {
303  const uint8_t* pixelTop = frameTop + CVUtilities::mirrorOffset(y + (unsigned int)(top), height) * frameStrideElements;
304  const uint8_t* pixelBottom = frameBottom + CVUtilities::mirrorOffset(y + (unsigned int)(top) + 1u, height) * frameStrideElements;
305 
306  for (int xSigned = left; xSigned < left + int(patchSize); ++xSigned)
307  {
308  const unsigned int x = (unsigned int)(xSigned);
309 
310  if (x < width && (x + 1u) < width)
311  {
312  // both pixels lies inside the frame
313 
314  for (unsigned int n = 0u; n < tChannels; ++n)
315  {
316  buffer[n] = uint8_t((pixelTop[0] * tx_y_ + pixelTop[tChannels] * txy_ + pixelBottom[0] * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
317 
318  ++pixelTop;
319  ++pixelBottom;
320  }
321  }
322  else if (x < width)
323  {
324  // x0 lies inside the frame
325 
326  ocean_assert(x + 1u >= width);
327 
328  const int offset = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
329 
330  for (unsigned int n = 0u; n < tChannels; ++n)
331  {
332  buffer[n] = uint8_t((pixelTop[0] * tx_y_ + *(pixelTop + offset) * txy_ + pixelBottom[0] * tx_y + *(pixelBottom + offset) * txy + 8192u) >> 14u);
333 
334  ++pixelTop;
335  ++pixelBottom;
336  }
337  }
338  else if (x + 1u < width)
339  {
340  // x1 lies inside the frame
341 
342  ocean_assert(x >= width);
343 
344  const int offset = CVUtilities::mirrorOffset(x, width) * int(tChannels);
345 
346  for (unsigned int n = 0u; n < tChannels; ++n)
347  {
348  buffer[n] = uint8_t((*(pixelTop + 0 + offset) * tx_y_ + pixelTop[tChannels] * txy_ + *(pixelBottom + 0 + offset) * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
349 
350  ++pixelTop;
351  ++pixelBottom;
352  }
353  }
354  else
355  {
356  // neither x0 nor x1 lies inside the frame
357 
358  ocean_assert(x >= width && x + 1u >= width);
359 
360  const int offsetLeft = CVUtilities::mirrorOffset(x, width) * int(tChannels);
361  const int offsetRight = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
362 
363  for (unsigned int n = 0u; n < tChannels; ++n)
364  {
365  buffer[n] = uint8_t((*(pixelTop + 0 + offsetLeft) * tx_y_ + *(pixelTop + offsetRight) * txy_ + *(pixelBottom + 0 + offsetLeft) * tx_y + *(pixelBottom + offsetRight) * txy + 8192u) >> 14u);
366 
367  ++pixelTop;
368  ++pixelBottom;
369  }
370  }
371 
372  buffer += tChannels;
373  }
374 
375  frameTop += frameStrideElements;
376  frameBottom += frameStrideElements;
377  }
378 }
379 
380 template <unsigned int tChannels, unsigned int tPatchSize>
381 void AdvancedFrameInterpolatorBilinearBase::interpolateSquareMirroredBorderTemplate8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position)
382 {
383  static_assert(tChannels >= 1u, "Invalid channel number!");
384  static_assert(tPatchSize >= 1u && tPatchSize % 2u == 1u, "The patch size must be odd!");
385 
386  ocean_assert(frame != nullptr && buffer != nullptr);
387 
388  constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
389 
390  ocean_assert(position.x() >= 0 && position.y() >= 0);
391  ocean_assert(position.x() < Scalar(width) && position.y() < Scalar(height));
392 
393  const int left = int(position.x()) - int(tPatchSize_2);
394  const int top = int(position.y()) - int(tPatchSize_2);
395 
396  const Scalar tx = position.x() - Scalar(tPatchSize_2) - Scalar(left);
397  ocean_assert(tx >= 0 && tx <= 1);
398  const unsigned int txi = (unsigned int)(tx * Scalar(128) + Scalar(0.5));
399  const unsigned int txi_ = 128u - txi;
400 
401  const Scalar ty = position.y() - Scalar(tPatchSize_2) - Scalar(top);
402  ocean_assert(ty >= 0 && ty <= 1);
403  const unsigned int tyi = (unsigned int)(ty * Scalar(128) + Scalar(0.5));
404  const unsigned int tyi_ = 128u - tyi;
405 
406  const unsigned int tx_y_ = txi_ * tyi_;
407  const unsigned int txy_ = txi * tyi_;
408  const unsigned int tx_y = txi_ * tyi;
409  const unsigned int txy = txi * tyi;
410 
411  const int frameStrideElements = int(width * tChannels + framePaddingElements);
412 
413  const uint8_t* frameTop = frame + top * frameStrideElements + left * int(tChannels);
414  const uint8_t* frameBottom = frameTop + frameStrideElements;
415 
416  for (unsigned int y = 0u; y < tPatchSize; ++y)
417  {
418  const uint8_t* pixelTop = frameTop + CVUtilities::mirrorOffset(y + (unsigned int)(top), height) * frameStrideElements;
419  const uint8_t* pixelBottom = frameBottom + CVUtilities::mirrorOffset(y + (unsigned int)(top) + 1u, height) * frameStrideElements;
420 
421  for (int xSigned = left; xSigned < left + int(tPatchSize); ++xSigned)
422  {
423  const unsigned int x = (unsigned int)(xSigned);
424 
425  if (x < width && (x + 1u) < width)
426  {
427  // both pixels lies inside the frame
428 
429  for (unsigned int n = 0u; n < tChannels; ++n)
430  {
431  buffer[n] = uint8_t((pixelTop[0] * tx_y_ + pixelTop[tChannels] * txy_ + pixelBottom[0] * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
432 
433  ++pixelTop;
434  ++pixelBottom;
435  }
436  }
437  else if (x < width)
438  {
439  // x0 lies inside the frame
440 
441  ocean_assert(x + 1u >= width);
442 
443  const int offset = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
444 
445  for (unsigned int n = 0u; n < tChannels; ++n)
446  {
447  buffer[n] = uint8_t((pixelTop[0] * tx_y_ + *(pixelTop + offset) * txy_ + pixelBottom[0] * tx_y + *(pixelBottom + offset) * txy + 8192u) >> 14u);
448 
449  ++pixelTop;
450  ++pixelBottom;
451  }
452  }
453  else if (x + 1u < width)
454  {
455  // x1 lies inside the frame
456 
457  ocean_assert(x >= width);
458 
459  const int offset = CVUtilities::mirrorOffset(x, width) * int(tChannels);
460 
461  for (unsigned int n = 0u; n < tChannels; ++n)
462  {
463  buffer[n] = uint8_t((*(pixelTop + 0 + offset) * tx_y_ + pixelTop[tChannels] * txy_ + *(pixelBottom + 0 + offset) * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
464 
465  ++pixelTop;
466  ++pixelBottom;
467  }
468  }
469  else
470  {
471  // neither x0 nor x1 lies inside the frame
472 
473  ocean_assert(x >= width && x + 1u >= width);
474 
475  const int offsetLeft = CVUtilities::mirrorOffset(x, width) * int(tChannels);
476  const int offsetRight = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
477 
478  for (unsigned int n = 0u; n < tChannels; ++n)
479  {
480  buffer[n] = uint8_t((*(pixelTop + 0 + offsetLeft) * tx_y_ + *(pixelTop + offsetRight) * txy_ + *(pixelBottom + 0 + offsetLeft) * tx_y + *(pixelBottom + offsetRight) * txy + 8192u) >> 14u);
481 
482  ++pixelTop;
483  ++pixelBottom;
484  }
485  }
486 
487  buffer += tChannels;
488  }
489 
490  frameTop += frameStrideElements;
491  frameBottom += frameStrideElements;
492  }
493 }
494 
495 template <unsigned int tChannels>
496 inline void AdvancedFrameInterpolatorBilinearBase::interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int xFactor, const unsigned int yFactor)
497 {
498  ocean_assert(sourceTopLeft && target);
499  ocean_assert(xFactor <= 128u && yFactor <= 128u);
500 
501  interpolatePixel8BitPerChannel<tChannels>(sourceTopLeft, sourceBottomLeft, target, (128u - xFactor) * (128u - yFactor), xFactor * (128u - yFactor), (128u - xFactor) * yFactor, xFactor * yFactor);
502 }
503 
504 template <unsigned int tChannels>
505 inline void AdvancedFrameInterpolatorBilinearBase::interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int tx_ty_, const unsigned int txty_, const unsigned int tx_ty, const unsigned int txty)
506 {
507  ocean_assert(sourceTopLeft && target);
508  ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
509 
510  for (unsigned int n = 0u; n < tChannels; ++n)
511  {
512  target[n] = uint8_t((sourceTopLeft[n] * tx_ty_ + sourceTopLeft[tChannels + n] * txty_ + sourceBottomLeft[n] * tx_ty + sourceBottomLeft[tChannels + n] * txty + 8192u) >> 14u);
513  }
514 }
515 
516 }
517 
518 }
519 
520 }
521 
522 #endif // META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_BASE_H
This class implements several advanced bilinear frame interpolator functions based e....
Definition: AdvancedFrameInterpolatorBilinearBase.h:33
static void interpolatePatch8BitPerChannel(const uint8_t *const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t *buffer, const VectorT2< TScalar > &position, const unsigned int patchWidth, const unsigned int patchHeight)
Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores th...
Definition: AdvancedFrameInterpolatorBilinearBase.h:197
static void interpolatePixel8BitPerChannel(const uint8_t *sourceTopLeft, const uint8_t *sourceBottomLeft, uint8_t *target, const unsigned int xFactor, const unsigned int yFactor)
Interpolates the content of 2x2 pixels to one pixel.
Definition: AdvancedFrameInterpolatorBilinearBase.h:496
static void interpolateSquareMirroredBorderTemplate8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t *buffer, const Vector2 &position)
Interpolates the content of a square region inside a given frame into a buffer with size of the squar...
Definition: AdvancedFrameInterpolatorBilinearBase.h:381
static void interpolateSquarePatch8BitPerChannelTemplate(const uint8_t *const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t *buffer, const VectorT2< TScalar > &position)
Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and sto...
Definition: AdvancedFrameInterpolatorBilinearBase.h:126
static void interpolateSquareMirroredBorder8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t *buffer, const Vector2 &position, const unsigned int patchSize)
Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and sto...
Definition: AdvancedFrameInterpolatorBilinearBase.h:268
static int mirrorOffset(const unsigned int index, const unsigned int elements)
Deprecated.
Definition: CVUtilities.h:446
This class implements a vector with two elements.
Definition: Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
@ PC_TOP_LEFT
The center of a pixel is in the upper-left corner of each pixel's square.
Definition: CV.h:133
float Scalar
Definition of a scalar type.
Definition: Math.h:128
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15