| 116 | } |
| 117 | |
| 118 | std::string ResizeKernel::GetCVKernelBody(TContext* context) const { |
| 119 | auto kernel_sig = GetCVKernelSignature(context); |
| 120 | std::string body_temp = R"( |
| 121 | #include <math.h> |
| 122 | #include <string.h> |
| 123 | #include "tinycv_c.h" |
| 124 | #define rep(i, n) for (int i = 0; i < (n); ++i) |
| 125 | static inline uint8_t output_converter(float x){ |
| 126 | x = fmin(255.0f, fmax(0.0f, x)); |
| 127 | return (uint8_t) roundf(x); |
| 128 | } |
| 129 | static inline void get_nearest_linear_coord(float scale, int size, int idx, float* ah0, int* ih0, float* ah1, int* ih1){ |
| 130 | if (size == 1) { |
| 131 | *ah0 = 1.f; |
| 132 | *ih0 = 0; |
| 133 | *ah1 = 0.f; |
| 134 | *ih1 = 0; |
| 135 | } |
| 136 | |
| 137 | float alpha = (idx + 0.5f) / scale - 0.5f; |
| 138 | int origin_idx = (int)(floorf(alpha)); |
| 139 | alpha -= origin_idx; |
| 140 | |
| 141 | if (origin_idx < 0) { |
| 142 | origin_idx = 0; |
| 143 | alpha = 0; |
| 144 | } else if (origin_idx + 1 >= size) { |
| 145 | origin_idx = size - 2; |
| 146 | alpha = 1; |
| 147 | } |
| 148 | |
| 149 | *ah0 = 1 - alpha; |
| 150 | *ih0 = origin_idx; |
| 151 | *ah1 = alpha; |
| 152 | *ih1 = origin_idx + 1; |
| 153 | } |
| 154 | void ${kernel_sig}{ |
| 155 | uint8_t * sptr = src->data; |
| 156 | uint8_t * dptr = dst->data; |
| 157 | int IH = src->rows; |
| 158 | int IW = src->cols; |
| 159 | int C = src->channels; |
| 160 | int OH = dst->rows; |
| 161 | int OW = dst->cols; |
| 162 | |
| 163 | float scale_h = (float)(OH) / IH; |
| 164 | float scale_w = (float)(OW) / IW; |
| 165 | |
| 166 | rep(oh, OH) rep(ow, OW) { |
| 167 | int ih0, ih1, iw0, iw1; |
| 168 | float ah0, ah1, aw0, aw1; |
| 169 | |
| 170 | get_nearest_linear_coord(scale_h, IH, oh, &ah0, &ih0, &ah1, &ih1); |
| 171 | |
| 172 | get_nearest_linear_coord(scale_w, IW, ow, &aw0, &iw0, &aw1, &iw1); |
| 173 | |
| 174 | rep(c, C) { |
| 175 | dptr[(oh * OW + ow) * C + c] = output_converter( |
nothing calls this directly
no test coverage detected