#include <algorithm>
#include <cmath>
#include <cstdint>

namespace {

inline int clamp(int v, int lo, int hi) {
  return std::max(lo, std::min(v, hi));
}

}  // namespace

void resize_rgba_to_rgb24x24(const uint8_t* rgba, int width, int height, uint8_t* out_rgb) {
  constexpr int OUT = 24;
  for (int oy = 0; oy < OUT; oy++) {
    const float src_y = (oy + 0.5f) * static_cast<float>(height) / OUT - 0.5f;
    const int y0 = clamp(static_cast<int>(std::floor(src_y)), 0, height - 1);
    const int y1 = clamp(y0 + 1, 0, height - 1);
    const float fy = src_y - y0;

    for (int ox = 0; ox < OUT; ox++) {
      const float src_x = (ox + 0.5f) * static_cast<float>(width) / OUT - 0.5f;
      const int x0 = clamp(static_cast<int>(std::floor(src_x)), 0, width - 1);
      const int x1 = clamp(x0 + 1, 0, width - 1);
      const float fx = src_x - x0;

      for (int c = 0; c < 3; c++) {
        const float p00 = rgba[(y0 * width + x0) * 4 + c];
        const float p10 = rgba[(y0 * width + x1) * 4 + c];
        const float p01 = rgba[(y1 * width + x0) * 4 + c];
        const float p11 = rgba[(y1 * width + x1) * 4 + c];
        const float v = (1 - fy) * ((1 - fx) * p00 + fx * p10) + fy * ((1 - fx) * p01 + fx * p11);
        out_rgb[(oy * OUT + ox) * 3 + c] = static_cast<uint8_t>(std::round(v));
      }
    }
  }
}
