Wildmeshing Toolkit
bicubic_interpolation.cpp
Go to the documentation of this file.
2 
3 #include <wmtk/utils/Logger.hpp>
4 
7  const size_t width,
8  const size_t height,
9  const float* buffer,
10  const double sx_,
11  const double sy_,
12  const WrappingMode mode_x,
13  const WrappingMode mode_y)
14 {
15  BicubicVector<float> samples;
16 
17  const auto get_coordinate = [](const int x, const int size, const WrappingMode mode) -> int {
18  switch (mode) {
19  case WrappingMode::REPEAT: return (x + size) % size;
20 
22  if (x < 0)
23  return -(x % size);
24  else if (x < size)
25  return x;
26  else
27  return size - 1 - (x - size) % size;
28  case WrappingMode::CLAMP_TO_EDGE: return std::clamp(x, 0, size - 1);
29  default: return (x + size) % size;
30  }
31  };
32  const auto get_buffer_value = [&](int xx, int yy) -> float {
33  xx = get_coordinate(xx, static_cast<int>(width), mode_x);
34  yy = get_coordinate(yy, static_cast<int>(height), mode_y);
35  const int index = (yy % height) * width + (xx % width);
36  return buffer[index];
37  };
38 
39  const auto sx = static_cast<int>(std::floor(sx_ - 0.5));
40  const auto sy = static_cast<int>(std::floor(sy_ - 0.5));
41 
42  samples(0) = get_buffer_value(sx - 1, sy - 1);
43  samples(1) = get_buffer_value(sx, sy - 1);
44  samples(2) = get_buffer_value(sx + 1, sy - 1);
45  samples(3) = get_buffer_value(sx + 2, sy - 1);
46 
47  samples(4) = get_buffer_value(sx - 1, sy);
48  samples(5) = get_buffer_value(sx, sy);
49  samples(6) = get_buffer_value(sx + 1, sy);
50  samples(7) = get_buffer_value(sx + 2, sy);
51 
52  samples(8) = get_buffer_value(sx - 1, sy + 1);
53  samples(9) = get_buffer_value(sx, sy + 1);
54  samples(10) = get_buffer_value(sx + 1, sy + 1);
55  samples(11) = get_buffer_value(sx + 2, sy + 1);
56 
57  samples(12) = get_buffer_value(sx - 1, sy + 2);
58  samples(13) = get_buffer_value(sx, sy + 2);
59  samples(14) = get_buffer_value(sx + 1, sy + 2);
60  samples(15) = get_buffer_value(sx + 2, sy + 2);
61 
62  return samples;
63 }
64 
66 {
67  BicubicMatrix ope;
68  Eigen::Index row = 0;
69  for (float yy = -1; yy < 3; yy++)
70  for (float xx = -1; xx < 3; xx++) {
71  ope(row, 0) = 1;
72  ope(row, 1) = xx;
73  ope(row, 2) = xx * xx;
74  ope(row, 3) = xx * xx * xx;
75 
76  ope(row, 4) = yy;
77  ope(row, 5) = xx * yy;
78  ope(row, 6) = xx * xx * yy;
79  ope(row, 7) = xx * xx * xx * yy;
80 
81  ope(row, 8) = yy * yy;
82  ope(row, 9) = xx * yy * yy;
83  ope(row, 10) = xx * xx * yy * yy;
84  ope(row, 11) = xx * xx * xx * yy * yy;
85 
86  ope(row, 12) = yy * yy * yy;
87  ope(row, 13) = xx * yy * yy * yy;
88  ope(row, 14) = xx * xx * yy * yy * yy;
89  ope(row, 15) = xx * xx * xx * yy * yy * yy;
90 
91  row++;
92  }
93 
94  {
95  std::stringstream ss;
96  ss << ope << std::endl;
97  logger().debug("ope det {}\n{}", ope.determinant(), ss.str());
98  }
99 
100  // invert operator
101  BicubicMatrix ope_inv = ope.inverse();
102 
103  // prune "zeros"
104  ope_inv = ope_inv.unaryExpr([](const float& xx) { return fabs(xx) < 1e-5f ? 0 : xx; });
105 
106  {
107  std::stringstream ss;
108  ss << ope_inv << std::endl;
109  logger().debug("ope_inv det {}\n{}", ope_inv.determinant(), ss.str());
110  }
111 
112  // double check inverse property
113  assert((ope * ope_inv - BicubicMatrix::Identity()).array().abs().maxCoeff() < 1e-5);
114 
115  return ope_inv;
116 }
117 
119 {
121  return mat;
122 }
123 } // namespace wmtk::components::adaptive_tessellation::image
BicubicVector< float > extract_samples(const size_t width, const size_t height, const float *buffer, const double sx_, const double sy_, const WrappingMode mode_x, const WrappingMode mode_y)
Rational abs(const Rational &r0)
Definition: Rational.cpp:328
spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:58