Skip to content

Instantly share code, notes, and snippets.

@lrw04
Created June 21, 2023 03:49
Show Gist options
  • Save lrw04/84b67813ec6fcc79c7b3876feca73aa8 to your computer and use it in GitHub Desktop.
Save lrw04/84b67813ec6fcc79c7b3876feca73aa8 to your computer and use it in GitHub Desktop.
C++ code for resizing images.
#include <cassert>
#include <string>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"
#include "stb_image_write.h"
float fb(float x) {
x = abs(x);
if (x < 1) return (-3 * pow(1 - x, 3) + 3 * pow(1 - x, 2) + 3 * (1 - x) + 1) / 6;
if (x < 2) return pow(2 - x, 3) / 6;
return 0;
}
float fc(float x) {
x = abs(x);
if (x < 1) return (-3 * pow(1 - x, 3) + 4 * pow(1 - x, 2) + (1 - x)) / 2;
if (x < 2) return (pow(2 - x, 3) - pow(2 - x, 2)) / 2;
return 0;
}
float fm(float x) {
return fb(x) / 3 + 2 * fc(x) / 3;
}
vector<vector<float>> transpose(const vector<vector<float>> &a) {
int n = a.size(), m = a[0].size();
vector<vector<float>> b(m, vector<float>(n));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) b[j][i] = a[i][j];
return b;
}
float reconstruct(const vector<float> &a, float x) {
float s = 0;
int r = 2;
for (int i = floor(x - r); i <= ceil(x + r); i++) {
// cerr << i << endl;
s += (i < 0 ? a[0] : (i >= a.size() ? a.back() : a[i])) * fm(x - i);
}
// cerr << endl;
return s;
}
vector<float> resample(const vector<float> &a, int new_w) {
int w = a.size();
vector<float> b(new_w);
// new pixel width is new_w / w
float dx = (float) w / new_w, x0 = dx - 1.0f;
for (int i = 0; i < new_w; i++) {
cerr << x0 + i * dx << endl;
b[i] = reconstruct(a, x0 + i * dx);
}
return b;
}
// imgproc in.png out.png 100 (new-width)
int main(int argc, char **argv) {
assert(argc == 4);
string in = argv[1], out = argv[2];
int new_w = stoi(argv[3]);
int w, h, c;
uint8_t *data = stbi_load(in.c_str(), &w, &h, &c, 0);
int new_h = h * new_w / w;
assert(data);
vector<vector<vector<float>>> dat(c, vector<vector<float>>(h, vector<float>(w)));
vector<vector<vector<float>>> int_dat(c, vector<vector<float>>(h));
vector<vector<vector<float>>> out_dat(c, vector<vector<float>>(new_w));
for (int i = 0; i < c; i++) {
for (int j = 0; j < h; j++) {
for (int k = 0; k < w; k++) {
dat[i][j][k] = data[(j * w + k) * c + i] / 256.0f;
}
}
}
for (int k = 0; k < c; k++) {
for (int i = 0; i < h; i++) {
int_dat[k][i] = resample(dat[k][i], new_w);
}
int_dat[k] = transpose(int_dat[k]);
}
for (int k = 0; k < c; k++) {
for (int i = 0; i < new_w; i++) {
out_dat[k][i] = resample(int_dat[k][i], new_h);
}
out_dat[k] = transpose(out_dat[k]);
}
vector<uint8_t> out_data;
for (int i = 0; i < new_h; i++) {
for (int j = 0; j < new_w; j++) {
for (int k = 0; k < c; k++) {
out_data.push_back(clamp((int) (out_dat[k][i][j] * 256), 0, 255));
}
}
}
stbi_write_png(out.c_str(), new_w, new_h, c, out_data.data(), new_w * c);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment