Ocean
Loading...
Searching...
No Matches
FrameEnlarger.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_FRAME_ENLARGER_H
9#define META_OCEAN_CV_FRAME_ENLARGER_H
10
11#include "ocean/cv/CV.h"
13
14#include "ocean/base/DataType.h"
15#include "ocean/base/Frame.h"
16#include "ocean/base/Worker.h"
17
18namespace Ocean
19{
20
21namespace CV
22{
23
24/**
25 * This class implements functions to enlarge/up-sample frames.
26 * @ingroup cv
27 */
28class OCEAN_CV_EXPORT FrameEnlarger
29{
30 public:
31
32 /**
33 * The following comfort class provides comfortable functions simplifying prototyping applications but also increasing binary size of the resulting applications.
34 * Best practice is to avoid using these functions if binary size matters,<br>
35 * as for every comfort function a corresponding function exists with specialized functionality not increasing binary size significantly.<br>
36 */
37 class OCEAN_CV_EXPORT Comfort
38 {
39 public:
40
41 /**
42 * Adds a border to the given frame while all new pixels will receive a specified border color.
43 * @param source The source frame to be extended with a border, must be valid
44 * @param target The target frame receiving the extended frame, will be set to the correct pixel format and frame dimension
45 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, infinity)
46 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, infinity)
47 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, infinity)
48 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, infinity)
49 * @param color The border color to be used for the new border pixels, one value for each channel, must be valid
50 * @return True, if succeeded
51 */
52 static bool addBorder(const Frame& source, Frame& target, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const void* color);
53
54 /**
55 * Adds a border to the given frame while all new pixels will receive a specified border color.
56 * @param frame The frame to be extended by a border, must be valid
57 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, infinity)
58 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, infinity)
59 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, infinity)
60 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, infinity)
61 * @param color The border color to be used for the new border pixels, one value for each channel, must be valid
62 * @return True, if succeeded
63 */
64 static inline bool addBorder(Frame& frame, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const void* color);
65
66 /**
67 * Adds a border to the given frame.
68 * The color of the border pixels are defined by the nearest pixels of the original frame.
69 * @param source The source frame to be extended with a border, must be valid
70 * @param target The target frame receiving the extended frame, will be set to the correct pixel format and frame dimension
71 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, infinity)
72 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, infinity)
73 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, infinity)
74 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, infinity)
75 * @return True, if succeeded
76 */
77 static bool addBorderNearestPixel(const Frame& source, Frame& target, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom);
78
79 /**
80 * Adds a border to the given frame.
81 * The color of the border pixels are defined by the nearest pixels of the original frame.
82 * @param frame The frame to be extended by a border, must be valid
83 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, infinity)
84 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, infinity)
85 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, infinity)
86 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, infinity)
87 * @return True, if succeeded
88 */
89 static inline bool addBorderNearestPixel(Frame& frame, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom);
90
91 /**
92 * Adds a border to the given frame by mirroring the frame border (and border neighbor) pixels.
93 * @param source The source frame to be extended with a border, must be valid
94 * @param target The target frame receiving the extended frame, will be set to the correct pixel format and frame dimension
95 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, frame.width()]
96 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, frame.height()]
97 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, frame.width()]
98 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, frame.height()]
99 * @return True, if succeeded
100 */
101 static bool addBorderMirrored(const Frame& source, Frame& target, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom);
102
103 /**
104 * Adds a border to the given frame by mirroring the frame border (and border neighbor) pixels.
105 * @param frame The frame to be extended by a border, must be valid
106 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, frame.width()]
107 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, frame.height()]
108 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, frame.width()]
109 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, frame.height()]
110 * @return True, if succeeded
111 */
112 static inline bool addBorderMirrored(Frame& frame, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom);
113
114 /**
115 * Doubles the size of a given frame by a pixel repeating upsampling.
116 * @param source The source (and untouched) frame to be upsized, must be valid
117 * @param target The target frame receiving the upsized frame, will be set to the correct pixel format and frame dimension
118 * @param worker Optional worker object to distribute the computation
119 * @return True, if succeeded
120 */
121 static bool multiplyByTwo(const Frame& source, Frame& target, Worker* worker = nullptr);
122
123 /**
124 * Adds a transparent border to a given frame.
125 * The color of the transparent border pixels are taken from the nearest image pixel.<br>
126 * @param source The source frame which will be extended with a transparent border
127 * @param target Resulting target frame with transparent border
128 * @param leftBorder Size of the left frame border in pixel, with range [0, infinity)
129 * @param topBorder Size of the top frame border in pixel, with range [0, infinity)
130 * @param rightBorder Size of the right frame border in pixel, with range [0, infinity)
131 * @param bottomBorder Size of the bottom frame border in pixel, with range [0, infinity)
132 * @return True, if succeeded
133 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
134 */
135 template <bool tTransparentIs0xFF>
136 static bool addTransparentBorder(const Frame& source, Frame& target, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder);
137
138 /**
139 * Adds a transparent border to a given frame.
140 * The color of the transparent border pixels are taken from the nearest image pixel.<br>
141 * @param frame The frame which will be extended with a transparent border
142 * @param leftBorder Size of the left frame border in pixel, with range [0, infinity)
143 * @param topBorder Size of the top frame border in pixel, with range [0, infinity)
144 * @param rightBorder Size of the right frame border in pixel, with range [0, infinity)
145 * @param bottomBorder Size of the bottom frame border in pixel, with range [0, infinity)
146 * @return True, if succeeded
147 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
148 */
149 template <bool tTransparentIs0xFF>
150 static bool addTransparentBorder(Frame& frame, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder);
151 };
152
153 /**
154 * Adds a transparent border to a given frame.
155 * The color of the transparent border pixels are taken from the nearest image pixel.<br>
156 * @param source The source frame which will be extended with a transparent border
157 * @param target Resulting target frame with transparent border
158 * @param width The width of the source frame in pixel, with range [1, infinity)
159 * @param height The height of the source frame in pixel, with range [1, infinity)
160 * @param leftBorder Size of the left frame border in pixel, with range [1, infinity)
161 * @param topBorder Size of the top frame border in pixel, with range [1, infinity)
162 * @param rightBorder Size of the right frame border in pixel, with range [1, infinity)
163 * @param bottomBorder Size of the bottom frame border in pixel, with range [1, infinity)
164 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
165 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
166 * @tparam tChannelsWithAlpha Number of channels in the source frame (including the alpha channel)
167 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
168 * @tparam tSourceHasAlpha True, if not only the source frame holds an alpha channel but also the target frame, however values in a target alpha channel will be untouched
169 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
170 */
171 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tSourceHasAlpha, bool tTransparentIs0xFF>
172 static void addTransparentBorder8BitPerChannel(const unsigned char* source, unsigned char* target, const unsigned int width, const unsigned int height, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements);
173
174 /**
175 * Adds a border to a given frame while all new pixels will receive a specified border color/value.
176 * @param source The source image to be extended, must be valid
177 * @param target The target image receiving the extended frame, with resolution (sourceWidth + borderSizeLeft + borderSizeRight)x(sourceHeight + borderSizeTop + borderSizeBottom), must be valid
178 * @param sourceWidth Width of the original source image in pixel, with range [1, infinity)
179 * @param sourceHeight Height of the original source image in pixel, with range [1, infinity)
180 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, infinity)
181 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, infinity)
182 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, infinity)
183 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, infinity)
184 * @param color Border color/value to be used for the new border pixels, must be tChannels values
185 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
186 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
187 * @tparam T The data type of a pixel channel
188 * @tparam tChannels The number of data channels, with range [1, infinity)
189 */
190 template <typename T, unsigned int tChannels>
191 static void addBorder(const T* source, T* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const T* color, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements);
192
193 /**
194 * Adds a border to a given frame while the color of the border pixels are defined by the nearest pixels of the original frame.
195 * @param source The source image to be extended, must be valid
196 * @param target The target image receiving the extended frame, with resolution (sourceWidth + borderSizeLeft + borderSizeRight)x(sourceHeight + borderSizeTop + borderSizeBottom), must be valid
197 * @param sourceWidth Width of the original source image in pixel, with range [1, infinity)
198 * @param sourceHeight Height of the original source image in pixel, with range [1, infinity)
199 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, infinity)
200 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, infinity)
201 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, infinity)
202 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, infinity)
203 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
204 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
205 * @tparam T The data type of a pixel channel
206 * @tparam tChannels The number of data channels, with range [1, infinity)
207 */
208 template <typename T, unsigned int tChannels>
209 static void addBorderNearestPixel(const T* source, T* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements);
210
211 /**
212 * Adds a border to a given frame by mirroring the frame's content.
213 * @param source The source image to be extended, must be valid
214 * @param target The target image receiving the extended frame, with resolution (sourceWidth + borderSizeLeft + borderSizeRight)x(sourceHeight + borderSizeTop + borderSizeBottom), must be valid
215 * @param sourceWidth Width of the original source image in pixel, with range [1, infinity)
216 * @param sourceHeight Height of the original source image in pixel, with range [1, infinity)
217 * @param borderSizeLeft The size of the border at the left image boundary, in pixel, with range [0, sourceWidth]
218 * @param borderSizeTop The size of the border at the top image boundary, in pixel, with range [0, sourceHeight]
219 * @param borderSizeRight The size of the border at the right image boundary, in pixel, with range [0, sourceWidth]
220 * @param borderSizeBottom The size of the border at the bottom image boundary, in pixel, with range [0, sourceHeight]
221 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
222 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
223 * @tparam T The data type of a pixel channel
224 * @tparam tChannels The number of data channels, with range [1, infinity)
225 */
226 template <typename T, unsigned int tChannels>
227 static void addBorderMirrored(const T* source, T* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements);
228
229 /**
230 * Doubles the size of a given frame by a pixel repeating upsampling.
231 * @param source Buffer of the source frame to be upsampled
232 * @param target Buffer of the target frame receiving the upsampled frame
233 * @param targetWidth Width of the target buffer in pixel, with range [2, infinity) and targetWidth / 2 == sourceWidth
234 * @param targetHeight Height of the target buffer in pixel, with range [2, infinity) and targetHeight / 2 == sourceHeight
235 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
236 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
237 * @param worker Optional worker object to distribute the computation
238 * @tparam T The data type of a pixel channel
239 * @tparam tChannels The number of data channels, with range [1, infinity)
240 */
241 template <typename T, unsigned int tChannels>
242 static void multiplyByTwo(const T* source, T* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
243
244 private:
245
246 /**
247 * Doubles a subset of a given frame by a pixel repeating upsampling.
248 * @param source Buffer of the source frame to be upsampled
249 * @param target Buffer of the target frame receiving the upsampled frame
250 * @param targetWidth Width of the target buffer in pixel, with range [2, infinity) and targetWidth / 2 == sourceWidth
251 * @param targetHeight Height of the target buffer in pixel, with range [2, infinity) and targetHeight / 2 == sourceHeight
252 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
253 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
254 * @param firstTargetRow First target row to be handled, with range [0, targetHeight)
255 * @param numberTargetRows Number of target rows to be handled, with range [1, targetHeight]
256 * @tparam T The data type of a pixel channel
257 * @tparam tChannels The number of data channels, with range [1, infinity)
258 */
259 template <typename T, unsigned int tChannels>
260 static void multiplyByTwoSubset(const T* source, T* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
261};
262
263inline bool FrameEnlarger::Comfort::addBorder(Frame& frame, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const void* color)
264{
265 ocean_assert(frame.isValid());
266 ocean_assert(color != nullptr);
267
268 Frame tmpFrame;
269 if (!addBorder(frame, tmpFrame, borderSizeLeft, borderSizeTop, borderSizeRight, borderSizeBottom, color))
270 {
271 return false;
272 }
273
274 tmpFrame.setTimestamp(frame.timestamp());
275 tmpFrame.setRelativeTimestamp(frame.relativeTimestamp());
276
277 frame = std::move(tmpFrame);
278 return true;
279}
280
281bool FrameEnlarger::Comfort::addBorderNearestPixel(Frame& frame, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom)
282{
283 ocean_assert(frame.isValid());
284
285 Frame tmpFrame;
286 if (!addBorderNearestPixel(frame, tmpFrame, borderSizeLeft, borderSizeTop, borderSizeRight, borderSizeBottom))
287 {
288 return false;
289 }
290
291 tmpFrame.setTimestamp(frame.timestamp());
292 tmpFrame.setRelativeTimestamp(frame.relativeTimestamp());
293
294 frame = std::move(tmpFrame);
295 return true;
296}
297
298bool FrameEnlarger::Comfort::addBorderMirrored(Frame& frame, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom)
299{
300 ocean_assert(frame.isValid());
301
302 Frame tmpFrame;
303 if (!addBorderMirrored(frame, tmpFrame, borderSizeLeft, borderSizeTop, borderSizeRight, borderSizeBottom))
304 {
305 return false;
306 }
307
308 tmpFrame.setTimestamp(frame.timestamp());
309 tmpFrame.setRelativeTimestamp(frame.relativeTimestamp());
310
311 frame = std::move(tmpFrame);
312 return true;
313}
314
315
316template <typename T, unsigned int tChannels>
317void FrameEnlarger::addBorder(const T* source, T* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const T* color, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
318{
319 static_assert(tChannels >= 1u, "Invalid channel number!");
320
321 ocean_assert(source != nullptr && target != nullptr);
322 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
323
324 typedef typename DataType<T, tChannels>::Type PixelType;
325 static_assert(sizeof(PixelType) == sizeof(T) * tChannels, "Invalid pixel type!");
326
327 const unsigned int targetWidth = sourceWidth + borderSizeLeft + borderSizeRight;
328
329 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
330 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
331
332 const PixelType borderColorPixel = *((const PixelType*)color);
333
334 if (borderSizeTop != 0u)
335 {
336 // top border rows
337
338 // first row
339 for (unsigned int n = 0u; n < targetWidth; ++n)
340 {
341 ((PixelType*)target)[n] = borderColorPixel;
342 }
343
344 // following top borders
345 for (unsigned int y = 1u; y < borderSizeTop; ++y)
346 {
347 memcpy(target + y * targetStrideElements, target, targetWidth * sizeof(PixelType));
348 }
349 }
350
351 for (unsigned int y = 0u; y < sourceHeight; ++y)
352 {
353 const PixelType* sourcePixel = (const PixelType*)(source + y * sourceStrideElements);
354 PixelType* targetPixel = (PixelType*)(target + (borderSizeTop + y) * targetStrideElements);
355
356 if (borderSizeTop == 0u)
357 {
358 for (unsigned int n = 0u; n < borderSizeLeft; ++n)
359 {
360 targetPixel[n] = borderColorPixel;
361 }
362 }
363 else
364 {
365 // left
366 memcpy(targetPixel, target, borderSizeLeft * sizeof(PixelType));
367 }
368
369 targetPixel += borderSizeLeft;
370
371 // center
372 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
373
374 targetPixel += sourceWidth;
375 sourcePixel += sourceWidth;
376
377 if (borderSizeTop == 0u)
378 {
379 for (unsigned int n = 0u; n < borderSizeRight; ++n)
380 {
381 targetPixel[n] = borderColorPixel;
382 }
383 }
384 else
385 {
386 // right
387 memcpy(targetPixel, target, borderSizeRight * sizeof(PixelType));
388 }
389 }
390
391 if (borderSizeBottom != 0u)
392 {
393 PixelType* targetPixel = (PixelType*)(target + (borderSizeTop + sourceHeight) * targetStrideElements);
394
395 // first row
396 for (unsigned int n = 0u; n < targetWidth; ++n)
397 {
398 targetPixel[n] = borderColorPixel;
399 }
400
401 // following top borders
402 for (unsigned int y = 1u; y < borderSizeBottom; ++y)
403 {
404 memcpy(target + (borderSizeTop + sourceHeight + y) * targetStrideElements, targetPixel, targetWidth * sizeof(PixelType));
405 }
406 }
407}
408
409template <typename T, unsigned int tChannels>
410void FrameEnlarger::addBorderNearestPixel(const T* source, T* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
411{
412 static_assert(tChannels >= 1u, "Invalid channel number!");
413
414 ocean_assert(source != nullptr && target != nullptr);
415 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
416
417 typedef typename DataType<T, tChannels>::Type PixelType;
418 static_assert(sizeof(PixelType) == sizeof(T) * tChannels, "Invalid pixel type!");
419
420 const unsigned int targetWidth = sourceWidth + borderSizeLeft + borderSizeRight;
421
422 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
423 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
424
425 const PixelType* sourcePixel = (const PixelType*)source;
426 PixelType* targetPixel = (PixelType*)target;
427
428 if (borderSizeTop != 0u)
429 {
430 // top border rows
431 for (unsigned int x = 0u; x < borderSizeLeft; ++x)
432 {
433 targetPixel[x] = *sourcePixel;
434 }
435
436 targetPixel += borderSizeLeft;
437
438 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
439 targetPixel += sourceWidth;
440
441 for (unsigned int x = 0u; x < borderSizeRight; ++x)
442 {
443 targetPixel[x] = sourcePixel[sourceWidth - 1u];
444 }
445
446 targetPixel += borderSizeRight;
447
448 // following top borders
449 for (unsigned int y = 1u; y < borderSizeTop; ++y)
450 {
451 memcpy(target + y * targetStrideElements, target, targetWidth * sizeof(PixelType));
452 }
453 }
454
455 // middle rows
456 for (unsigned int y = 0u; y < sourceHeight; ++y)
457 {
458 sourcePixel = (const PixelType*)(source + y * sourceStrideElements);
459 targetPixel = (PixelType*)(target + (borderSizeTop + y) * targetStrideElements);
460
461 // left border columns
462 for (unsigned int x = 0u; x < borderSizeLeft; ++x)
463 {
464 targetPixel[x] = *sourcePixel;
465 }
466
467 targetPixel += borderSizeLeft;
468
469 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
470
471 targetPixel += sourceWidth;
472 sourcePixel += sourceWidth - 1u;
473
474 // right border columns
475 for (unsigned int x = 0u; x < borderSizeRight; ++x)
476 {
477 targetPixel[x] = *sourcePixel;
478 }
479 }
480
481 if (borderSizeBottom != 0u)
482 {
483 sourcePixel = (const PixelType*)(source + (sourceHeight - 1u) * sourceStrideElements);
484 targetPixel = (PixelType*)(target + (borderSizeTop + sourceHeight) * targetStrideElements);
485
486 // first bottom row
487 for (unsigned int x = 0u; x < borderSizeLeft; ++x)
488 {
489 targetPixel[x] = *sourcePixel;
490 }
491
492 targetPixel += borderSizeLeft;
493
494 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
495 targetPixel += sourceWidth;
496
497 for (unsigned int x = 0u; x < borderSizeRight; ++x)
498 {
499 targetPixel[x] = sourcePixel[sourceWidth - 1u];
500 }
501
502 // following top borders
503 const unsigned int targetHeight = sourceHeight + borderSizeTop + borderSizeBottom;
504
505 targetPixel = (PixelType*)(target + (targetHeight - borderSizeBottom) * targetStrideElements);
506
507 for (unsigned int y = targetHeight - borderSizeBottom + 1u; y < targetHeight; ++y)
508 {
509 memcpy(target + y * targetStrideElements,targetPixel, targetWidth * sizeof(PixelType));
510 }
511 }
512}
513
514template <typename T, unsigned int tChannels>
515void FrameEnlarger::addBorderMirrored(const T* source, T* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
516{
517 static_assert(tChannels >= 1u, "Invalid channel number!");
518
519 ocean_assert(source != nullptr && target != nullptr);
520 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
521 ocean_assert(borderSizeLeft <= sourceWidth && borderSizeRight <= sourceWidth);
522 ocean_assert(borderSizeTop <= sourceHeight && borderSizeBottom <= sourceHeight);
523
524 typedef typename DataType<T, tChannels>::Type PixelType;
525 static_assert(sizeof(PixelType) == sizeof(T) * tChannels, "Invalid pixel type!");
526
527 const unsigned int targetWidth = sourceWidth + borderSizeLeft + borderSizeRight;
528
529 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
530 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
531
532 // top rows
533
534 for (unsigned int y = 0u; y < borderSizeTop; ++y)
535 {
536 const PixelType* sourcePixel = (const PixelType*)(source + (borderSizeTop - y - 1u) * sourceStrideElements);
537 PixelType* targetPixel = (PixelType*)(target + y * targetStrideElements);
538
539 // left
540 for (unsigned int n = 0u; n < borderSizeLeft; ++n)
541 {
542 targetPixel[n] = *(sourcePixel + borderSizeLeft - n - 1u);
543 }
544
545 targetPixel += borderSizeLeft;
546
547 // middle
548 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
549
550 targetPixel += sourceWidth;
551 sourcePixel += sourceWidth;
552
553 // right
554 for (unsigned int n = 0u; n < borderSizeRight; ++n)
555 {
556 targetPixel[n] = *(sourcePixel - n - 1u);
557 }
558 }
559
560 // middle rows
561
562 for (unsigned int y = 0u; y < sourceHeight; ++y)
563 {
564 const PixelType* sourcePixel = (const PixelType*)(source + y * sourceStrideElements);
565 PixelType* targetPixel = (PixelType*)(target + (borderSizeTop + y) * targetStrideElements);
566
567 // left
568 for (unsigned int n = 0u; n < borderSizeLeft; ++n)
569 {
570 targetPixel[n] = *(sourcePixel + borderSizeLeft - n - 1u);
571 }
572
573 targetPixel += borderSizeLeft;
574
575 // middle
576 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
577
578 targetPixel += sourceWidth;
579 sourcePixel += sourceWidth;
580
581 // right
582 for (unsigned int n = 0u; n < borderSizeRight; ++n)
583 {
584 targetPixel[n] = *(sourcePixel - n - 1u);
585 }
586 }
587
588 for (unsigned int y = 0u; y < borderSizeBottom; ++y)
589 {
590 const PixelType* sourcePixel = (const PixelType*)(source + (sourceHeight - y - 1u) * sourceStrideElements);
591 PixelType* targetPixel = (PixelType*)(target + (borderSizeTop + sourceHeight + y) * targetStrideElements);
592
593 // left
594 for (unsigned int n = 0u; n < borderSizeLeft; ++n)
595 {
596 targetPixel[n] = *(sourcePixel + borderSizeLeft - n - 1u);
597 }
598
599 targetPixel += borderSizeLeft;
600
601 // middle
602 memcpy(targetPixel, sourcePixel, sourceWidth * sizeof(PixelType));
603
604 targetPixel += sourceWidth;
605 sourcePixel += sourceWidth;
606
607 // right
608 for (unsigned int n = 0u; n < borderSizeRight; ++n)
609 {
610 targetPixel[n] = *(sourcePixel - n - 1u);
611 }
612 }
613}
614
615template <bool tTransparentIs0xFF>
616bool FrameEnlarger::Comfort::addTransparentBorder(const Frame& source, Frame& target, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder)
617{
618 ocean_assert(source);
619
620 if (leftBorder == 0u && topBorder == 0u && rightBorder == 0u && bottomBorder == 0u)
621 {
622 target = source;
623 return true;
624 }
625
626 if (source.numberPlanes() == 1u)
627 {
629
630 const bool sourceHasAlpha = FrameType::formatHasAlphaChannel(source.pixelFormat());
631
632 if (sourceHasAlpha)
633 {
634 targetPixelFormat = source.pixelFormat();
635 }
637 {
638 targetPixelFormat = target.pixelFormat();
639 }
640 else
641 {
642 targetPixelFormat = FrameType::formatAddAlphaChannel(source.pixelFormat());
643 }
644
645 if (!target.set(FrameType(source.width() + leftBorder + rightBorder, source.height() + topBorder + bottomBorder, targetPixelFormat, source.pixelOrigin()), false /*forceOwner*/, true /*forceWritable*/))
646 {
647 ocean_assert(false && "This should never happen!");
648 return false;
649 }
650
651 ocean_assert(target && FrameType::formatHasAlphaChannel(target.pixelFormat()));
652
653 if (!target)
654 {
655 return false;
656 }
657
658 bool alphaAtBack = false;
659 const bool tmpResult = FrameType::formatHasAlphaChannel(target.pixelFormat(), &alphaAtBack);
660 ocean_assert_and_suppress_unused(tmpResult, tmpResult);
661
662 switch (target.channels())
663 {
664 case 2u:
665 {
666 if (alphaAtBack)
667 {
668 if (sourceHasAlpha)
669 {
670 addTransparentBorder8BitPerChannel<2u, false, true, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
671 }
672 else
673 {
674 addTransparentBorder8BitPerChannel<2u, false, false, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
675 }
676 }
677 else
678 {
679 if (sourceHasAlpha)
680 {
681 addTransparentBorder8BitPerChannel<2u, true, true, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
682 }
683 else
684 {
685 addTransparentBorder8BitPerChannel<2u, true, false, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
686 }
687 }
688
689 return true;
690 }
691
692 case 3u:
693 {
694 if (alphaAtBack)
695 {
696 if (sourceHasAlpha)
697 {
698 addTransparentBorder8BitPerChannel<3u, false, true, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
699 }
700 else
701 {
702 addTransparentBorder8BitPerChannel<3u, false, false, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
703 }
704 }
705 else
706 {
707 if (sourceHasAlpha)
708 {
709 addTransparentBorder8BitPerChannel<3u, true, true, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
710 }
711 else
712 {
713 addTransparentBorder8BitPerChannel<3u, true, false, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
714 }
715 }
716
717 return true;
718 }
719
720 case 4u:
721 {
722 if (alphaAtBack)
723 {
724 if (sourceHasAlpha)
725 {
726 addTransparentBorder8BitPerChannel<4u, false, true, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
727 }
728 else
729 {
730 addTransparentBorder8BitPerChannel<4u, false, false, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
731 }
732 }
733 else
734 {
735 if (sourceHasAlpha)
736 {
737 addTransparentBorder8BitPerChannel<4u, true, true, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
738 }
739 else
740 {
741 addTransparentBorder8BitPerChannel<4u, true, false, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), source.width(), source.height(), leftBorder, topBorder, rightBorder, bottomBorder, source.paddingElements(), target.paddingElements());
742 }
743 }
744
745 return true;
746 }
747
748 default:
749 ocean_assert(false && "Missing implementation");
750 break;
751 }
752 }
753
754 return false;
755}
756
757template <bool tTransparentIs0xFF>
758bool FrameEnlarger::Comfort::addTransparentBorder(Frame& frame, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder)
759{
760 ocean_assert(frame.isValid());
761
762 Frame tmpFrame;
763 if (!addTransparentBorder<tTransparentIs0xFF>(frame, tmpFrame, leftBorder, topBorder, rightBorder, bottomBorder))
764 {
765 return false;
766 }
767
768 tmpFrame.setTimestamp(frame.timestamp());
769 tmpFrame.setRelativeTimestamp(frame.relativeTimestamp());
770
771 frame = std::move(tmpFrame);
772 return true;
773}
774
775template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tSourceHasAlpha, bool tTransparentIs0xFF>
776void FrameEnlarger::addTransparentBorder8BitPerChannel(const unsigned char* source, unsigned char* target, const unsigned int width, const unsigned int height, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
777{
778 ocean_assert(source && target);
779
780 typedef typename DataType<uint8_t, tChannelsWithAlpha - 1u>::Type TypeWithoutAlpha;
781
782 if (topBorder != 0u)
783 {
784 // first row, left block: use the color values of the top left pixel of the source frame
785 for (unsigned int x = 0u; x < leftBorder; ++x)
786 {
787 *(TypeWithoutAlpha*)(target + x * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
788 *(TypeWithoutAlpha*)(source + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
789
790 *(target + x * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
791 }
792
793 // first row, center block: use the color values of the top row of the source frame
794 for (unsigned int x = 0u; x < width; ++x)
795 {
796 *(TypeWithoutAlpha*)(target + (x + leftBorder) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
797 *(TypeWithoutAlpha*)(source + x * FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
798
799 *(target + (x + leftBorder) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
800 }
801
802 // first row, right block: use the color values of the top right pixel of the source frame
803 for (unsigned int x = 0u; x < rightBorder; ++x)
804 {
805 *(TypeWithoutAlpha*)(target + (x + leftBorder + width) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
806 *(TypeWithoutAlpha*)(source + (width - 1u) * FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
807
808 *(target + (x + leftBorder + width) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
809 }
810
811 // the remaining rows of the top border are copies of the first row
812 for (unsigned int y = 1u; y < topBorder; ++y)
813 {
814 memcpy(target + y * (width + leftBorder + rightBorder) * tChannelsWithAlpha + targetPaddingElements, target, (width + leftBorder + rightBorder) * tChannelsWithAlpha);
815 }
816
817 // next row
818 target += topBorder * (tChannelsWithAlpha * (width + leftBorder + rightBorder) + targetPaddingElements);
819 }
820
821
822 for (unsigned int y = 0u; y < height; ++y)
823 {
824 // left border
825 for (unsigned int x = 0u; x < leftBorder; ++x)
826 {
827 *(TypeWithoutAlpha*)(target + x * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
828 *(TypeWithoutAlpha*)(source + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
829
830 *(target + x * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
831 }
832
833 // center block
834 if constexpr (tSourceHasAlpha)
835 {
836 memcpy(target + leftBorder * tChannelsWithAlpha, source, width * tChannelsWithAlpha);
837 }
838 else
839 {
840 for (unsigned int x = 0u; x < width; ++x)
841 {
842 *(TypeWithoutAlpha*)(target + (x + leftBorder) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
843 *(TypeWithoutAlpha*)(source + x * FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
844
845 *(target + (x + leftBorder) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullOpaque8Bit<tTransparentIs0xFF>();
846 }
847 }
848
849 // right border
850 for (unsigned int x = 0u; x < rightBorder; ++x)
851 {
852 *(TypeWithoutAlpha*)(target + (x + leftBorder + width) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
853 *(TypeWithoutAlpha*)(source + (width - 1u) * FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
854
855 *(target + (x + leftBorder + width) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
856 }
857
858 // next row
859 source += FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() * width + sourcePaddingElements;
860 target += tChannelsWithAlpha * (width + leftBorder + rightBorder) + targetPaddingElements;
861 }
862
863 if (bottomBorder != 0u)
864 {
865 // we need the last row of the source frame
866 source -= FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() * width + sourcePaddingElements;
867
868 // first row of bottom border, left block: use the color values of the bottom left pixel of the source frame
869 for (unsigned int x = 0u; x < leftBorder; ++x)
870 {
871 *(TypeWithoutAlpha*)(target + x * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
872 *(TypeWithoutAlpha*)(source + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
873
874 *(target + x * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
875 }
876
877 // first row of the bottom border, center block: use the color values of the top row of the source frame
878 for (unsigned int x = 0u; x < width; ++x)
879 {
880 *(TypeWithoutAlpha*)(target + (x + leftBorder) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
881 *(TypeWithoutAlpha*)(source + x * FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
882
883 *(target + (x + leftBorder) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
884 }
885
886 // first row of the bottom border, right block: use the color values of the top right pixel of the source frame
887 for (unsigned int x = 0u; x < rightBorder; ++x)
888 {
889 *(TypeWithoutAlpha*)(target + (x + leftBorder + width) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::data()) =
890 *(TypeWithoutAlpha*)(source + (width - 1u) * FrameBlender::FrameChannels<tSourceHasAlpha>::template channels<tChannelsWithAlpha>() + FrameBlender::SourceOffset<tAlphaAtFront>::template data<tSourceHasAlpha>());
891
892 *(target + (x + leftBorder + width) * tChannelsWithAlpha + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()) = FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>();
893 }
894
895 // the remaining rows of the bottom border are copies of the first row
896 for (unsigned int y = 1u; y < bottomBorder; ++y)
897 {
898 memcpy(target + y * (width + leftBorder + rightBorder) * tChannelsWithAlpha + targetPaddingElements, target, (width + leftBorder + rightBorder) * tChannelsWithAlpha);
899 }
900 }
901}
902
903template <typename T, unsigned int tChannels>
904void FrameEnlarger::multiplyByTwo(const T* source, T* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
905{
906 ocean_assert(targetWidth >= 2u && targetHeight >= 2u);
907
908 if (worker)
909 {
910 worker->executeFunction(Worker::Function::createStatic(&FrameEnlarger::multiplyByTwoSubset<T, tChannels>, source, target, targetWidth, targetHeight, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, targetHeight);
911 }
912 else
913 {
914 multiplyByTwoSubset<T, tChannels>(source, target, targetWidth, targetHeight, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
915 }
916}
917
918template <typename T, unsigned int tChannels>
919void FrameEnlarger::multiplyByTwoSubset(const T* source, T* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
920{
921 ocean_assert(targetWidth >= 2u && targetHeight >= 2u);
922
923 ocean_assert(source && target);
924 ocean_assert(firstTargetRow + numberTargetRows <= targetHeight);
925
926 const unsigned int sourceWidth = targetWidth / 2u;
927 const unsigned int sourceHeight = targetHeight / 2u;
928 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
929
930 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
931 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
932
933 typedef typename DataType<T, tChannels>::Type PixelType;
934
935 // check whether no extra right column handling is necessary
936 if (targetWidth % 2u == 0u)
937 {
938 for (unsigned int targetRowIndex = firstTargetRow; targetRowIndex < (firstTargetRow + numberTargetRows); ++targetRowIndex)
939 {
940 const PixelType* sourcePixel = (const PixelType*)(source + min(targetRowIndex / 2u, sourceHeight - 1u) * sourceStrideElements);
941
942 PixelType* targetPixel = (PixelType*)(target + targetRowIndex * targetStrideElements);
943
944 const PixelType* const targetRowEnd = targetPixel + targetWidth;
945
946 while (targetPixel != targetRowEnd)
947 {
948 ocean_assert(targetPixel < targetRowEnd);
949
950 *targetPixel++ = *sourcePixel;
951
952 ocean_assert(targetPixel < targetRowEnd);
953
954 *targetPixel++ = *sourcePixel++;
955 }
956 }
957 }
958 else
959 {
960 ocean_assert((targetWidth - 1u) % 2u == 0u);
961
962 for (unsigned int targetRowIndex = firstTargetRow; targetRowIndex < (firstTargetRow + numberTargetRows); ++targetRowIndex)
963 {
964 const PixelType* sourcePixel = (const PixelType*)(source + min(targetRowIndex / 2u, sourceHeight - 1u) * sourcePaddingElements);
965 --sourcePixel;
966
967 PixelType* targetPixel = (PixelType*)(target + targetRowIndex * targetStrideElements);
968
969 const PixelType* const targetRowEnd = targetPixel + targetWidth - 1u;
970
971 while (targetPixel != targetRowEnd)
972 {
973 ocean_assert(targetPixel < targetRowEnd);
974
975 *targetPixel++ = *++sourcePixel;
976
977 ocean_assert(targetPixel < targetRowEnd);
978
979 *targetPixel++ = *sourcePixel;
980 }
981
982 // special handling for the last column
983 *targetPixel++ = *sourcePixel;
984 }
985 }
986}
987
988}
989
990}
991
992#endif // META_OCEAN_CV_FRAME_ENLARGER_H
Helper class allowing to determine the number of channels of a frame.
Definition FrameBlender.h:117
Helper class allowing to determine the offset that is necessary to access the alpha channel.
Definition FrameBlender.h:60
static constexpr unsigned int data()
Returns the offset that is applied to access the first data channel.
Definition FrameBlender.h:1160
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition FrameEnlarger.h:38
static bool addBorder(const Frame &source, Frame &target, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const void *color)
Adds a border to the given frame while all new pixels will receive a specified border color.
static bool addTransparentBorder(const Frame &source, Frame &target, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder)
Adds a transparent border to a given frame.
Definition FrameEnlarger.h:616
static bool multiplyByTwo(const Frame &source, Frame &target, Worker *worker=nullptr)
Doubles the size of a given frame by a pixel repeating upsampling.
static bool addBorderMirrored(const Frame &source, Frame &target, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom)
Adds a border to the given frame by mirroring the frame border (and border neighbor) pixels.
static bool addBorderNearestPixel(const Frame &source, Frame &target, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom)
Adds a border to the given frame.
This class implements functions to enlarge/up-sample frames.
Definition FrameEnlarger.h:29
static void multiplyByTwoSubset(const T *source, T *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Doubles a subset of a given frame by a pixel repeating upsampling.
Definition FrameEnlarger.h:919
static void addTransparentBorder8BitPerChannel(const unsigned char *source, unsigned char *target, const unsigned int width, const unsigned int height, const unsigned int leftBorder, const unsigned int topBorder, const unsigned int rightBorder, const unsigned int bottomBorder, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Adds a transparent border to a given frame.
Definition FrameEnlarger.h:776
static void addBorderMirrored(const T *source, T *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Adds a border to a given frame by mirroring the frame's content.
Definition FrameEnlarger.h:515
static void addBorder(const T *source, T *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const T *color, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Adds a border to a given frame while all new pixels will receive a specified border color/value.
Definition FrameEnlarger.h:317
static void addBorderNearestPixel(const T *source, T *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int borderSizeLeft, const unsigned int borderSizeTop, const unsigned int borderSizeRight, const unsigned int borderSizeBottom, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Adds a border to a given frame while the color of the border pixels are defined by the nearest pixels...
Definition FrameEnlarger.h:410
static void multiplyByTwo(const T *source, T *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Doubles the size of a given frame by a pixel repeating upsampling.
Definition FrameEnlarger.h:904
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition Caller.h:2876
Template class allowing to define an array of data types.
Definition DataType.h:27
This class implements Ocean's image class.
Definition Frame.h:1808
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition Frame.h:4248
void setRelativeTimestamp(const Timestamp &relative)
Sets the relative timestamp of this frame.
Definition Frame.h:4233
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition Frame.h:4239
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4528
void setTimestamp(const Timestamp &timestamp)
Sets the timestamp of this frame.
Definition Frame.h:4228
bool set(const FrameType &frameType, const bool forceOwner, const bool forceWritable=false, const Indices32 &planePaddingElements=Indices32(), const Timestamp &timestamp=Timestamp(false), bool *reallocated=nullptr)
Sets a new frame type for this frame.
const Timestamp & timestamp() const
Returns the timestamp of this frame.
Definition Frame.h:4218
const Timestamp & relativeTimestamp() const
Returns the relative timestamp of this frame.
Definition Frame.h:4223
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition Frame.h:4122
Definition of a frame type composed by the frame dimension, pixel format and pixel origin.
Definition Frame.h:30
PixelFormat
Definition of all pixel formats available in the Ocean framework.
Definition Frame.h:183
@ FORMAT_UNDEFINED
Undefined pixel format.
Definition Frame.h:187
unsigned int width() const
Returns the width of the frame format in pixel.
Definition Frame.h:3170
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition Frame.h:3215
uint32_t numberPlanes() const
Returns the number of planes of the pixel format of this frame.
Definition Frame.h:3210
static PixelFormat formatRemoveAlphaChannel(const PixelFormat pixelFormat)
Removes an alpha channel from a given pixel format.
static bool formatHasAlphaChannel(const PixelFormat pixelFormat, bool *isLastChannel=nullptr)
Returns whether a given pixel format holds an alpha channel.
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition Frame.h:3180
unsigned int height() const
Returns the height of the frame in pixel.
Definition Frame.h:3175
unsigned int channels() const
Returns the number of individual channels the frame has.
Definition Frame.h:3200
static PixelFormat formatAddAlphaChannel(const PixelFormat pixelFormat, const bool lastChannel=true)
Adds an alpha channel to a given pixel format.
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Default definition of a type with tBytes bytes.
Definition DataType.h:32