34 #ifndef VP_IMAGE_TOOLS_WARP_H
35 #define VP_IMAGE_TOOLS_WARP_H
38 #include <visp3/core/vpImageTools.h>
58 const unsigned int expectedNbCols = 3, expectedNbRows1stOpt = 2, expectedNbRows2ndOpt = 3;
59 if (((T.
getRows() != expectedNbRows1stOpt) && (T.
getRows() != expectedNbRows2ndOpt)) || (T.
getCols() != expectedNbCols)) {
60 std::cerr <<
"Input transformation must be a (2x3) or (3x3) matrix." << std::endl;
68 const bool affine = (T.
getRows() == 2);
77 const unsigned int index_0 = 0;
78 const unsigned int index_1 = 1;
79 const unsigned int index_2 = 2;
80 double D = (M[index_0][index_0] * M[index_1][index_1]) - (M[index_0][index_1] * M[index_1][index_0]);
81 D = !
vpMath::nul(D, std::numeric_limits<double>::epsilon()) ? (1.0 / D) : 0;
82 double A11 = M[index_1][index_1] * D, A22 = M[index_0][index_0] * D;
83 M[index_0][index_0] = A11;
84 M[index_0][index_1] *= -D;
85 M[index_1][index_0] *= -D;
86 M[index_1][index_1] = A22;
87 double b1 = (-M[index_0][index_0] * M[index_0][index_2]) - (M[index_0][index_1] * M[index_1][index_2]);
88 double b2 = (-M[index_1][index_0] * M[index_0][index_2]) - (M[index_1][index_1] * M[index_1][index_2]);
89 M[index_0][index_2] = b1;
90 M[index_1][index_2] = b2;
96 if (fixedPointArithmetic && (!pixelCenter)) {
97 fixedPointArithmetic = checkFixedPoint(0, 0, M, affine) && checkFixedPoint(dst.
getWidth() - 1, 0, M, affine) &&
98 checkFixedPoint(0, dst.
getHeight() - 1, M, affine) &&
104 warpNN(src, M, dst, affine, pixelCenter, fixedPointArithmetic);
108 warpLinear(src, M, dst, affine, pixelCenter, fixedPointArithmetic);
112 template <
class Type>
114 bool centerCorner,
bool fixedPoint)
116 if (fixedPoint && (!centerCorner)) {
117 const int nbits = 16;
118 const int32_t precision = 1 << nbits;
119 const float precision_1 = 1 /
static_cast<float>(precision);
120 const unsigned int index_0 = 0;
121 const unsigned int index_1 = 1;
122 const unsigned int index_2 = 2;
123 int32_t a0_i32 =
static_cast<int32_t
>(T[index_0][index_0] * precision);
124 int32_t a1_i32 =
static_cast<int32_t
>(T[index_0][index_1] * precision);
125 int32_t a2_i32 =
static_cast<int32_t
>(T[index_0][index_2] * precision);
126 int32_t a3_i32 =
static_cast<int32_t
>(T[index_1][index_0] * precision);
127 int32_t a4_i32 =
static_cast<int32_t
>(T[index_1][index_1] * precision);
128 int32_t a5_i32 =
static_cast<int32_t
>(T[index_1][index_2] * precision);
129 int32_t a6_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[index_2][index_0] * precision) : 0;
130 int32_t a7_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[index_2][index_1] * precision) : 0;
131 int32_t a8_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[index_2][index_2] * precision) : 1;
133 int32_t height_1_i32 =
static_cast<int32_t
>((src.
getHeight() - 1) * precision) + 0x8000;
134 int32_t width_1_i32 =
static_cast<int32_t
>((src.
getWidth() - 1) * precision) + 0x8000;
137 unsigned int dst_height = dst.
getHeight();
138 unsigned int dst_width = dst.
getWidth();
139 for (
unsigned int i = 0; i < dst_height; ++i) {
143 for (
unsigned int j = 0; j < dst_width; ++j) {
144 if ((yi >= 0) && (yi < height_1_i32) && (xi >= 0) && (xi < width_1_i32)) {
145 float x_ = (xi >> nbits) + ((xi & 0xFFFF) * precision_1);
146 float y_ = (yi >> nbits) + ((yi & 0xFFFF) * precision_1);
150 dst[i][j] = src[y][x];
162 unsigned int dst_height = dst.
getHeight();
163 unsigned int dst_width = dst.
getWidth();
164 int src_height =
static_cast<int>(src.
getHeight());
165 int src_width =
static_cast<int>(src.
getWidth());
166 for (
unsigned int i = 0; i < dst_height; ++i) {
171 for (
unsigned int j = 0; j < dst_width; ++j) {
172 bool cond_on_y = (yi >= 0) && (yi <= ((src_height - 1) * wi));
173 bool cond_on_x = (xi >= 0) && (xi <= ((src_width - 1) * wi));
174 if ((wi != 0) && cond_on_y && cond_on_x) {
175 float w_ = (wi >> nbits) + ((wi & 0xFFFF) * precision_1);
176 float x_ = ((xi >> nbits) + ((xi & 0xFFFF) * precision_1)) / w_;
177 float y_ = ((yi >> nbits) + ((yi & 0xFFFF) * precision_1)) / w_;
182 dst[i][j] = src[y][x];
197 const unsigned int index_0 = 0;
198 const unsigned int index_1 = 1;
199 const unsigned int index_2 = 2;
200 double a0 = T[index_0][index_0];
201 double a1 = T[index_0][index_1];
202 double a2 = T[index_0][index_2];
203 double a3 = T[index_1][index_0];
204 double a4 = T[index_1][index_1];
205 double a5 = T[index_1][index_2];
206 double a6 = affine ? 0.0 : T[index_2][index_0];
207 double a7 = affine ? 0.0 : T[index_2][index_1];
208 double a8 = affine ? 1.0 : T[index_2][index_2];
210 unsigned int dst_height = dst.
getHeight();
211 unsigned int dst_width = dst.
getWidth();
212 for (
unsigned int i = 0; i < dst_height; ++i) {
213 for (
unsigned int j = 0; j < dst_width; ++j) {
214 double x = ((a0 * (centerCorner ? (j + 0.5) : j)) + (a1 * (centerCorner ? (i + 0.5) : i))) + a2;
215 double y = ((a3 * (centerCorner ? (j + 0.5) : j)) + (a4 * (centerCorner ? (i + 0.5) : i))) + a5;
216 double w = ((a6 * (centerCorner ? (j + 0.5) : j)) + (a7 * (centerCorner ? (i + 0.5) : i))) + a8;
218 if (
vpMath::nul(w, std::numeric_limits<double>::epsilon())) {
222 int x_ = centerCorner ? coordCast(x / w) :
vpMath::round(x / w);
223 int y_ = centerCorner ? coordCast(y / w) :
vpMath::round(y / w);
225 if ((x_ >= 0) && (x_ <
static_cast<int>(src.
getWidth())) && (y_ >= 0) && (y_ <
static_cast<int>(src.
getHeight()))) {
226 dst[i][j] = src[y_][x_];
233 template <
class Type>
235 bool centerCorner,
bool fixedPoint)
237 if (fixedPoint && (!centerCorner)) {
238 const int nbits = 16;
239 const uint64_t precision = 1 << nbits;
240 const float precision_1 = 1 /
static_cast<float>(precision);
241 const uint64_t precision2 = 1ULL << (2 * nbits);
242 const float precision_2 = 1 /
static_cast<float>(precision2);
243 const unsigned int index_0 = 0;
244 const unsigned int index_1 = 1;
245 const unsigned int index_2 = 2;
247 int64_t a0_i64 =
static_cast<int64_t
>(T[index_0][index_0] * precision);
248 int64_t a1_i64 =
static_cast<int64_t
>(T[index_0][index_1] * precision);
249 int64_t a2_i64 =
static_cast<int64_t
>(T[index_0][index_2] * precision);
250 int64_t a3_i64 =
static_cast<int64_t
>(T[index_1][index_0] * precision);
251 int64_t a4_i64 =
static_cast<int64_t
>(T[index_1][index_1] * precision);
252 int64_t a5_i64 =
static_cast<int64_t
>(T[index_1][index_2] * precision);
253 int64_t a6_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[index_2][index_0] * precision) : 0;
254 int64_t a7_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[index_2][index_1] * precision) : 0;
255 int64_t a8_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[index_2][index_2] * precision) : 1;
257 int64_t height_i64 =
static_cast<int64_t
>(src.
getHeight() * precision);
258 int64_t width_i64 =
static_cast<int64_t
>(src.
getWidth() * precision);
261 unsigned int dst_height = dst.
getHeight();
262 unsigned int dst_width = dst.
getWidth();
263 for (
unsigned int i = 0; i < dst_height; ++i) {
264 int64_t xi_ = a2_i64;
265 int64_t yi_ = a5_i64;
267 for (
unsigned int j = 0; j < dst_width; ++j) {
268 if ((yi_ >= 0) && (yi_ < height_i64) && (xi_ >= 0) && (xi_ < width_i64)) {
269 const int64_t xi_lower = xi_ & (~0xFFFF);
270 const int64_t yi_lower = yi_ & (~0xFFFF);
272 const int64_t t = yi_ - yi_lower;
273 const int64_t t_1 = precision - t;
274 const int64_t s = xi_ - xi_lower;
275 const int64_t s_1 = precision - s;
277 const int x_ =
static_cast<int>(xi_ >> nbits);
278 const int y_ =
static_cast<int>(yi_ >> nbits);
280 if ((y_ < (
static_cast<int>(src.
getHeight()) - 1)) && (x_ < (
static_cast<int>(src.
getWidth()) - 1))) {
281 const Type val00 = src[y_][x_];
282 const Type val01 = src[y_][x_ + 1];
283 const Type val10 = src[y_ + 1][x_];
284 const Type val11 = src[y_ + 1][x_ + 1];
285 const int64_t interp_i64 =
286 static_cast<int64_t
>(((s_1 * t_1) * val00) + ((s * t_1) * val01) + ((s_1 * t) * val10) + ((s * t) * val11));
287 const float interp = (interp_i64 >> (nbits * 2)) + ((interp_i64 & 0xFFFFFFFFU) * precision_2);
288 dst[i][j] = vpMath::saturate<Type>(interp);
290 else if (y_ < (
static_cast<int>(src.
getHeight()) - 1)) {
291 const Type val00 = src[y_][x_];
292 const Type val10 = src[y_ + 1][x_];
293 const int64_t interp_i64 =
static_cast<int64_t
>((t_1 * val00) + (t * val10));
294 const float interp = (interp_i64 >> nbits) + ((interp_i64 & 0xFFFF) * precision_1);
295 dst[i][j] = vpMath::saturate<Type>(interp);
297 else if (x_ < (
static_cast<int>(src.
getWidth()) - 1)) {
298 const Type val00 = src[y_][x_];
299 const Type val01 = src[y_][x_ + 1];
300 const int64_t interp_i64 =
static_cast<int64_t
>((s_1 * val00) + (s * val01));
301 const float interp = (interp_i64 >> nbits) + ((interp_i64 & 0xFFFF) * precision_1);
302 dst[i][j] = vpMath::saturate<Type>(interp);
305 dst[i][j] = src[y_][x_];
318 unsigned int dst_height = dst.
getHeight();
319 unsigned int dst_width = dst.
getWidth();
320 int src_height =
static_cast<int>(src.
getHeight());
321 int src_width =
static_cast<int>(src.
getWidth());
322 for (
unsigned int i = 0; i < dst_height; ++i) {
327 for (
unsigned int j = 0; j < dst_width; ++j) {
328 bool cond_on_y = (yi >= 0) && (yi <= ((src_height - 1) * wi));
329 bool cond_on_x = (xi >= 0) && (xi <= ((src_width - 1) * wi));
330 if ((wi != 0) && cond_on_y && cond_on_x) {
331 const float wi_ = (wi >> nbits) + ((wi & 0xFFFF) * precision_1);
332 const float xi_ = ((xi >> nbits) + ((xi & 0xFFFF) * precision_1)) / wi_;
333 const float yi_ = ((yi >> nbits) + ((yi & 0xFFFF) * precision_1)) / wi_;
335 const int x_ =
static_cast<int>(xi_);
336 const int y_ =
static_cast<int>(yi_);
338 const float t = yi_ - y_;
339 const float s = xi_ - x_;
341 if ((y_ < (src_height - 1)) && (x_ < (src_width - 1))) {
342 const float val00 =
static_cast<float>(src[y_][x_]);
343 const float val01 =
static_cast<float>(src[y_][x_ + 1]);
344 const float val10 =
static_cast<float>(src[y_ + 1][x_]);
345 const float val11 =
static_cast<float>(src[y_ + 1][x_ + 1]);
346 const float col0 = lerp(val00, val01, s);
347 const float col1 = lerp(val10, val11, s);
348 const float interp = lerp(col0, col1, t);
349 dst[i][j] = vpMath::saturate<Type>(interp);
351 else if (y_ < (src_height - 1)) {
352 const float val00 =
static_cast<float>(src[y_][x_]);
353 const float val10 =
static_cast<float>(src[y_ + 1][x_]);
354 const float interp = lerp(val00, val10, t);
355 dst[i][j] = vpMath::saturate<Type>(interp);
357 else if (x_ < (src_width - 1)) {
358 const float val00 =
static_cast<float>(src[y_][x_]);
359 const float val01 =
static_cast<float>(src[y_][x_ + 1]);
360 const float interp = lerp(val00, val01, s);
361 dst[i][j] = vpMath::saturate<Type>(interp);
364 dst[i][j] = src[y_][x_];
380 const unsigned int index_0 = 0;
381 const unsigned int index_1 = 1;
382 const unsigned int index_2 = 2;
383 double a0 = T[index_0][index_0];
384 double a1 = T[index_0][index_1];
385 double a2 = T[index_0][index_2];
386 double a3 = T[index_1][index_0];
387 double a4 = T[index_1][index_1];
388 double a5 = T[index_1][index_2];
389 double a6 = affine ? 0.0 : T[index_2][index_0];
390 double a7 = affine ? 0.0 : T[index_2][index_1];
391 double a8 = affine ? 1.0 : T[index_2][index_2];
393 unsigned int dst_height = dst.
getHeight();
394 unsigned int dst_width = dst.
getWidth();
395 int src_height =
static_cast<int>(src.
getHeight());
396 int src_width =
static_cast<int>(src.
getWidth());
397 for (
unsigned int i = 0; i < dst_height; ++i) {
398 for (
unsigned int j = 0; j < dst_width; ++j) {
399 double x = (a0 * (centerCorner ? (j + 0.5) : j)) + (a1 * (centerCorner ? (i + 0.5) : i)) + a2;
400 double y = (a3 * (centerCorner ? (j + 0.5) : j)) + (a4 * (centerCorner ? (i + 0.5) : i)) + a5;
401 double w = (a6 * (centerCorner ? (j + 0.5) : j)) + (a7 * (centerCorner ? (i + 0.5) : i)) + a8;
402 if (
vpMath::nul(w, std::numeric_limits<double>::epsilon())) {
406 x = (x / w) - (centerCorner ? 0.5 : 0);
407 y = (y / w) - (centerCorner ? 0.5 : 0);
409 int x_lower =
static_cast<int>(x);
410 int y_lower =
static_cast<int>(y);
411 bool stop_for_loop =
false;
412 if ((y_lower >= src_height) || (x_lower >= src_width) || (y < 0) || (x < 0)) {
413 stop_for_loop =
true;
415 if (!stop_for_loop) {
416 double s = x - x_lower;
417 double t = y - y_lower;
419 if ((y_lower < (src_height - 1)) && (x_lower < (src_width - 1))) {
420 const double val00 =
static_cast<double>(src[y_lower][x_lower]);
421 const double val01 =
static_cast<double>(src[y_lower][x_lower + 1]);
422 const double val10 =
static_cast<double>(src[y_lower + 1][x_lower]);
423 const double val11 =
static_cast<double>(src[y_lower + 1][x_lower + 1]);
424 const double col0 = lerp(val00, val01, s);
425 const double col1 = lerp(val10, val11, s);
426 const double interp = lerp(col0, col1, t);
427 dst[i][j] = vpMath::saturate<Type>(interp);
429 else if (y_lower < (src_height - 1)) {
430 const double val00 =
static_cast<double>(src[y_lower][x_lower]);
431 const double val10 =
static_cast<double>(src[y_lower + 1][x_lower]);
432 const double interp = lerp(val00, val10, t);
433 dst[i][j] = vpMath::saturate<Type>(interp);
435 else if (x_lower < (src_width - 1)) {
436 const double val00 =
static_cast<double>(src[y_lower][x_lower]);
437 const double val01 =
static_cast<double>(src[y_lower][x_lower + 1]);
438 const double interp = lerp(val00, val01, s);
439 dst[i][j] = vpMath::saturate<Type>(interp);
442 dst[i][j] = src[y_lower][x_lower];
453 const unsigned int index_0 = 0, index_1 = 1, index_2 = 2;
454 const int nbits = 16;
455 const int64_t precision = 1 << nbits;
456 const float precision_1 = 1.f /
static_cast<float>(precision);
457 const int64_t precision2 = 1ULL << (2 * nbits);
458 const float precision_2 = 1.f /
static_cast<float>(precision2);
460 int64_t a0_i64 =
static_cast<int64_t
>(T[index_0][index_0] * precision);
461 int64_t a1_i64 =
static_cast<int64_t
>(T[index_0][index_1] * precision);
462 int64_t a2_i64 =
static_cast<int64_t
>(T[index_0][index_2] * precision);
463 int64_t a3_i64 =
static_cast<int64_t
>(T[index_1][index_0] * precision);
464 int64_t a4_i64 =
static_cast<int64_t
>(T[index_1][index_1] * precision);
465 int64_t a5_i64 =
static_cast<int64_t
>(T[index_1][index_2] * precision);
466 int64_t a6_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[index_2][index_0] * precision) : 0;
467 int64_t a7_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[index_2][index_1] * precision) : 0;
468 int64_t a8_i64 = precision;
470 int64_t height_i64 =
static_cast<int64_t
>(src.
getHeight() * precision);
471 int64_t width_i64 =
static_cast<int64_t
>(src.
getWidth() * precision);
474 unsigned int dst_height = dst.
getHeight();
475 unsigned int dst_width = dst.
getWidth();
476 int src_height =
static_cast<int>(src.
getHeight());
477 int src_width =
static_cast<int>(src.
getWidth());
478 const unsigned char aChannelVal = 255;
479 for (
unsigned int i = 0; i < dst_height; ++i) {
483 for (
unsigned int j = 0; j < dst_width; ++j) {
484 if ((yi >= 0) && (yi < height_i64) && (xi >= 0) && (xi < width_i64)) {
485 const int64_t xi_lower = xi & (~0xFFFF);
486 const int64_t yi_lower = yi & (~0xFFFF);
488 const int64_t t = yi - yi_lower;
489 const int64_t t_1 = precision - t;
490 const int64_t s = xi - xi_lower;
491 const int64_t s_1 = precision - s;
493 const int x_ =
static_cast<int>(xi >> nbits);
494 const int y_ =
static_cast<int>(yi >> nbits);
496 if ((y_ < (src_height - 1)) && (x_ < (src_width - 1))) {
497 const vpRGBa val00 = src[y_][x_];
498 const vpRGBa val01 = src[y_][x_ + 1];
499 const vpRGBa val10 = src[y_ + 1][x_];
500 const vpRGBa val11 = src[y_ + 1][x_ + 1];
501 const int64_t interpR_i64 =
502 static_cast<int64_t
>((s_1 * t_1 * val00.
R) + (s * t_1 * val01.
R) + (s_1 * t * val10.
R) + (s * t * val11.
R));
503 const float interpR = (interpR_i64 >> (nbits * 2)) + ((interpR_i64 & 0xFFFFFFFFU) * precision_2);
505 const int64_t interpG_i64 =
506 static_cast<int64_t
>((s_1 * t_1 * val00.
G) + (s * t_1 * val01.
G) + (s_1 * t * val10.
G) + (s * t * val11.
G));
507 const float interpG = (interpG_i64 >> (nbits * 2)) + ((interpG_i64 & 0xFFFFFFFFU) * precision_2);
509 const int64_t interpB_i64 =
510 static_cast<int64_t
>((s_1 * t_1 * val00.
B) + (s * t_1 * val01.
B) + (s_1 * t * val10.
B) + (s * t * val11.
B));
511 const float interpB = (interpB_i64 >> (nbits * 2)) + ((interpB_i64 & 0xFFFFFFFFU) * precision_2);
513 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
514 vpMath::saturate<unsigned char>(interpB), aChannelVal);
516 else if (y_ < (src_height - 1)) {
517 const vpRGBa val00 = src[y_][x_];
518 const vpRGBa val10 = src[y_ + 1][x_];
519 const int64_t interpR_i64 =
static_cast<int64_t
>((t_1 * val00.
R) + (t * val10.
R));
520 const float interpR = (interpR_i64 >> nbits) + ((interpR_i64 & 0xFFFF) * precision_1);
522 const int64_t interpG_i64 =
static_cast<int64_t
>((t_1 * val00.
G) + (t * val10.
G));
523 const float interpG = (interpG_i64 >> nbits) + ((interpG_i64 & 0xFFFF) * precision_1);
525 const int64_t interpB_i64 =
static_cast<int64_t
>((t_1 * val00.
B) + (t * val10.
B));
526 const float interpB = (interpB_i64 >> nbits) + ((interpB_i64 & 0xFFFF) * precision_1);
528 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
529 vpMath::saturate<unsigned char>(interpB), aChannelVal);
531 else if (x_ < (src_width - 1)) {
532 const vpRGBa val00 = src[y_][x_];
533 const vpRGBa val01 = src[y_][x_ + 1];
534 const int64_t interpR_i64 =
static_cast<int64_t
>((s_1 * val00.
R) + (s * val01.
R));
535 const float interpR = (interpR_i64 >> nbits) + ((interpR_i64 & 0xFFFF) * precision_1);
537 const int64_t interpG_i64 =
static_cast<int64_t
>((s_1 * val00.
G) + (s * val01.
G));
538 const float interpG = (interpG_i64 >> nbits) + ((interpG_i64 & 0xFFFF) * precision_1);
540 const int64_t interpB_i64 =
static_cast<int64_t
>((s_1 * val00.
B) + (s * val01.
B));
541 const float interpB = (interpB_i64 >> nbits) + ((interpB_i64 & 0xFFFF) * precision_1);
543 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
544 vpMath::saturate<unsigned char>(interpB), aChannelVal);
547 dst[i][j] = src[y_][x_];
560 unsigned int dst_height = dst.
getHeight();
561 unsigned int dst_width = dst.
getWidth();
562 int src_height =
static_cast<int>(src.
getHeight());
563 int src_width =
static_cast<int>(src.
getWidth());
564 const unsigned char aChannelVal = 255;
565 for (
unsigned int i = 0; i < dst_height; ++i) {
570 for (
unsigned int j = 0; j < dst_width; ++j) {
571 if ((yi >= 0) && (yi <= ((src_height - 1) * wi)) && (xi >= 0) &&
572 (xi <= ((src_width - 1) * wi))) {
573 const float wi_ = (wi >> nbits) + ((wi & 0xFFFF) * precision_1);
574 const float xi_ = ((xi >> nbits) + ((xi & 0xFFFF) * precision_1)) / wi_;
575 const float yi_ = ((yi >> nbits) + ((yi & 0xFFFF) * precision_1)) / wi_;
577 const int x_ =
static_cast<int>(xi_);
578 const int y_ =
static_cast<int>(yi_);
580 const float t = yi_ - y_;
581 const float s = xi_ - x_;
583 if ((y_ < (src_height - 1)) && (x_ < (src_width - 1))) {
584 const vpRGBa val00 = src[y_][x_];
585 const vpRGBa val01 = src[y_][x_ + 1];
586 const vpRGBa val10 = src[y_ + 1][x_];
587 const vpRGBa val11 = src[y_ + 1][x_ + 1];
588 const float colR0 = lerp(val00.
R, val01.
R, s);
589 const float colR1 = lerp(val10.
R, val11.
R, s);
590 const float interpR = lerp(colR0, colR1, t);
592 const float colG0 = lerp(val00.
G, val01.
G, s);
593 const float colG1 = lerp(val10.
G, val11.
G, s);
594 const float interpG = lerp(colG0, colG1, t);
596 const float colB0 = lerp(val00.
B, val01.
B, s);
597 const float colB1 = lerp(val10.
B, val11.
B, s);
598 const float interpB = lerp(colB0, colB1, t);
600 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
601 vpMath::saturate<unsigned char>(interpB), aChannelVal);
603 else if (y_ < (src_height - 1)) {
604 const vpRGBa val00 = src[y_][x_];
605 const vpRGBa val10 = src[y_ + 1][x_];
606 const float interpR = lerp(val00.
R, val10.
R, t);
607 const float interpG = lerp(val00.
G, val10.
G, t);
608 const float interpB = lerp(val00.
B, val10.
B, t);
610 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
611 vpMath::saturate<unsigned char>(interpB), aChannelVal);
613 else if (x_ < (src_width - 1)) {
614 const vpRGBa val00 = src[y_][x_];
615 const vpRGBa val01 = src[y_][x_ + 1];
616 const float interpR = lerp(val00.
R, val01.
R, s);
617 const float interpG = lerp(val00.
G, val01.
G, s);
618 const float interpB = lerp(val00.
B, val01.
B, s);
620 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
621 vpMath::saturate<unsigned char>(interpB), aChannelVal);
624 dst[i][j] = src[y_][x_];
643 bool centerCorner,
bool fixedPoint)
645 const unsigned int index_0 = 0, index_1 = 1, index_2 = 2;
646 if (fixedPoint && (!centerCorner)) {
647 warpLinearFixedPointNotCenter(src, T, dst, affine);
650 double a0 = T[index_0][index_0];
651 double a1 = T[index_0][index_1];
652 double a2 = T[index_0][index_2];
653 double a3 = T[index_1][index_0];
654 double a4 = T[index_1][index_1];
655 double a5 = T[index_1][index_2];
656 double a6 = affine ? 0.0 : T[index_2][index_0];
657 double a7 = affine ? 0.0 : T[index_2][index_1];
658 double a8 = affine ? 1.0 : T[index_2][index_2];
660 unsigned int dst_height = dst.
getHeight();
661 unsigned int dst_width = dst.
getWidth();
662 int src_height =
static_cast<int>(src.
getHeight());
663 int src_width =
static_cast<int>(src.
getWidth());
664 const unsigned char aChannelVal = 255;
665 for (
unsigned int i = 0; i < dst_height; ++i) {
666 for (
unsigned int j = 0; j < dst_width; ++j) {
667 double x = (a0 * (centerCorner ? (j + 0.5) : j)) + (a1 * (centerCorner ? (i + 0.5) : i)) + a2;
668 double y = (a3 * (centerCorner ? (j + 0.5) : j)) + (a4 * (centerCorner ? (i + 0.5) : i)) + a5;
669 double w = (a6 * (centerCorner ? (j + 0.5) : j)) + (a7 * (centerCorner ? (i + 0.5) : i)) + a8;
671 x = (x / w) - (centerCorner ? 0.5 : 0);
672 y = (y / w) - (centerCorner ? 0.5 : 0);
674 int x_lower =
static_cast<int>(x);
675 int y_lower =
static_cast<int>(y);
677 bool stop_for_loop =
false;
678 if ((y_lower >= src_height) || (x_lower >= src_width) || (y < 0) || (x < 0)) {
679 stop_for_loop =
true;
681 if (!stop_for_loop) {
682 double s = x - x_lower;
683 double t = y - y_lower;
685 if ((y_lower < (src_height - 1)) && (x_lower < (src_width - 1))) {
686 const vpRGBa val00 = src[y_lower][x_lower];
687 const vpRGBa val01 = src[y_lower][x_lower + 1];
688 const vpRGBa val10 = src[y_lower + 1][x_lower];
689 const vpRGBa val11 = src[y_lower + 1][x_lower + 1];
690 const double colR0 = lerp(val00.
R, val01.
R, s);
691 const double colR1 = lerp(val10.
R, val11.
R, s);
692 const double interpR = lerp(colR0, colR1, t);
694 const double colG0 = lerp(val00.
G, val01.
G, s);
695 const double colG1 = lerp(val10.
G, val11.
G, s);
696 const double interpG = lerp(colG0, colG1, t);
698 const double colB0 = lerp(val00.
B, val01.
B, s);
699 const double colB1 = lerp(val10.
B, val11.
B, s);
700 const double interpB = lerp(colB0, colB1, t);
702 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
703 vpMath::saturate<unsigned char>(interpB), aChannelVal);
705 else if (y_lower < (src_height - 1)) {
706 const vpRGBa val00 = src[y_lower][x_lower];
707 const vpRGBa val10 = src[y_lower + 1][x_lower];
708 const double interpR = lerp(val00.
R, val10.
R, t);
709 const double interpG = lerp(val00.
G, val10.
G, t);
710 const double interpB = lerp(val00.
B, val10.
B, t);
712 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
713 vpMath::saturate<unsigned char>(interpB), aChannelVal);
715 else if (x_lower < (src_width - 1)) {
716 const vpRGBa val00 = src[y_lower][x_lower];
717 const vpRGBa val01 = src[y_lower][x_lower + 1];
718 const double interpR = lerp(val00.
R, val01.
R, s);
719 const double interpG = lerp(val00.
G, val01.
G, s);
720 const double interpB = lerp(val00.
B, val01.
B, s);
722 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR), vpMath::saturate<unsigned char>(interpG),
723 vpMath::saturate<unsigned char>(interpB), aChannelVal);
726 dst[i][j] = src[y_lower][x_lower];
unsigned int getCols() const
unsigned int getRows() const
Definition of the vpImage class member functions.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getSize() const
unsigned int getHeight() const
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
static bool nul(double x, double threshold=0.001)
static int round(double x)
Implementation of a matrix and operations on matrices.
vpMatrix inverseByLU() const
unsigned char B
Blue component.
unsigned char R
Red component.
unsigned char G
Green component.