123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- #include <Arduino.h>
- float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
- void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y,
- float f);
- void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols,
- int8_t x, int8_t y);
- void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols,
- int8_t x, int8_t y);
- float cubicInterpolate(float p[], float x);
- float bicubicInterpolate(float p[], float x, float y);
- void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
- float *dest, uint8_t dest_rows, uint8_t dest_cols);
- float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y) {
- if (x < 0) x = 0;
- if (y < 0) y = 0;
- if (x >= cols) x = cols - 1;
- if (y >= rows) y = rows - 1;
- return p[y * cols + x];
- }
- void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y,
- float f) {
- if ((x < 0) || (x >= cols)) return;
- if ((y < 0) || (y >= rows)) return;
- p[y * cols + x] = f;
- }
- // src is a grid src_rows * src_cols
- // dest is a pre-allocated grid, dest_rows*dest_cols
- void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
- float *dest, uint8_t dest_rows, uint8_t dest_cols) {
- float mu_x = (src_cols - 1.0) / (dest_cols - 1.0);
- float mu_y = (src_rows - 1.0) / (dest_rows - 1.0);
- float adj_2d[16]; // matrix for storing adjacents
- for (uint8_t y_idx = 0; y_idx < dest_rows; y_idx++) {
- for (uint8_t x_idx = 0; x_idx < dest_cols; x_idx++) {
- float x = x_idx * mu_x;
- float y = y_idx * mu_y;
- // Serial.print("("); Serial.print(y_idx); Serial.print(", ");
- // Serial.print(x_idx); Serial.print(") = "); Serial.print("(");
- // Serial.print(y); Serial.print(", "); Serial.print(x);
- // Serial.print(") = ");
- get_adjacents_2d(src, adj_2d, src_rows, src_cols, x, y);
- /*
- Serial.print("[");
- for (uint8_t i=0; i<16; i++) {
- Serial.print(adj_2d[i]); Serial.print(", ");
- }
- Serial.println("]");
- */
- float frac_x =
- x - (int)x; // we only need the ~delta~ between the points
- float frac_y =
- y - (int)y; // we only need the ~delta~ between the points
- float out = bicubicInterpolate(adj_2d, frac_x, frac_y);
- // Serial.print("\tInterp: "); Serial.println(out);
- set_point(dest, dest_rows, dest_cols, x_idx, y_idx, out);
- }
- }
- }
- // p is a list of 4 points, 2 to the left, 2 to the right
- float cubicInterpolate(float p[], float x) {
- float r = p[1] + (0.5 * x *
- (p[2] - p[0] +
- x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] +
- x * (3.0 * (p[1] - p[2]) + p[3] - p[0]))));
- /*
- Serial.print("interpolating: [");
- Serial.print(p[0],2); Serial.print(", ");
- Serial.print(p[1],2); Serial.print(", ");
- Serial.print(p[2],2); Serial.print(", ");
- Serial.print(p[3],2); Serial.print("] w/"); Serial.print(x);
- Serial.print(" = "); Serial.println(r);
- */
- return r;
- }
- // p is a 16-point 4x4 array of the 2 rows & columns left/right/above/below
- float bicubicInterpolate(float p[], float x, float y) {
- float arr[4] = {0, 0, 0, 0};
- arr[0] = cubicInterpolate(p + 0, x);
- arr[1] = cubicInterpolate(p + 4, x);
- arr[2] = cubicInterpolate(p + 8, x);
- arr[3] = cubicInterpolate(p + 12, x);
- return cubicInterpolate(arr, y);
- }
- // src is rows*cols and dest is a 4-point array passed in already allocated!
- void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols,
- int8_t x, int8_t y) {
- // Serial.print("("); Serial.print(x); Serial.print(", "); Serial.print(y);
- // Serial.println(")");
- // pick two items to the left
- dest[0] = get_point(src, rows, cols, x - 1, y);
- dest[1] = get_point(src, rows, cols, x, y);
- // pick two items to the right
- dest[2] = get_point(src, rows, cols, x + 1, y);
- dest[3] = get_point(src, rows, cols, x + 2, y);
- }
- // src is rows*cols and dest is a 16-point array passed in already allocated!
- void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols,
- int8_t x, int8_t y) {
- // Serial.print("("); Serial.print(x); Serial.print(", "); Serial.print(y);
- // Serial.println(")");
- float arr[4];
- for (int8_t delta_y = -1; delta_y < 3; delta_y++) { // -1, 0, 1, 2
- float *row = dest + 4 * (delta_y + 1); // index into each chunk of 4
- for (int8_t delta_x = -1; delta_x < 3; delta_x++) { // -1, 0, 1, 2
- row[delta_x + 1] =
- get_point(src, rows, cols, x + delta_x, y + delta_y);
- }
- }
- }
|