Skip to content

Instantly share code, notes, and snippets.

@dionyziz
Last active November 21, 2019 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dionyziz/49696a58d072daebea91f4bdb7183203 to your computer and use it in GitHub Desktop.
Save dionyziz/49696a58d072daebea91f4bdb7183203 to your computer and use it in GitHub Desktop.
#include <cstdio>
#include <iostream>
#include <cairo.h>
using namespace std;
struct RGBA {
int a, r, g, b;
};
const int bytes_per_row = 4;
const int BLUR = 20;
RGBA read_pixel(int w, int h, unsigned char* data, int x, int y) {
RGBA ret;
int stride = bytes_per_row * w;
int a_loc = stride * y + x * bytes_per_row + 0,
r_loc = stride * y + x * bytes_per_row + 1,
g_loc = stride * y + x * bytes_per_row + 2,
b_loc = stride * y + x * bytes_per_row + 3;
ret.a = data[a_loc];
ret.r = data[r_loc];
ret.g = data[g_loc];
ret.b = data[b_loc];
return ret;
}
void write_pixel(int w, int h, unsigned char* data, int x, int y, RGBA pixel) {
int stride = bytes_per_row * w;
int a_loc = stride * y + x * bytes_per_row + 0,
r_loc = stride * y + x * bytes_per_row + 1,
g_loc = stride * y + x * bytes_per_row + 2,
b_loc = stride * y + x * bytes_per_row + 3;
data[a_loc] = pixel.a;
data[r_loc] = pixel.r;
data[g_loc] = pixel.g;
data[b_loc] = pixel.b;
}
void add_pixel(RGBA &dest, RGBA src) {
dest.a += src.a;
dest.r += src.r;
dest.g += src.g;
dest.b += src.b;
}
void scale_pixel(RGBA &pixel, float lambda) {
pixel.a *= lambda;
pixel.r *= lambda;
pixel.g *= lambda;
pixel.b *= lambda;
}
int main() {
cairo_surface_t* source_surface = cairo_image_surface_create_from_png("dionyziz.png");
cairo_format_t source_fmt = cairo_image_surface_get_format(source_surface);
int w = cairo_image_surface_get_width(source_surface);
int h = cairo_image_surface_get_height(source_surface);
int stride = cairo_image_surface_get_stride(source_surface);
int bytes_per_row = stride / w;
unsigned char* source_data = cairo_image_surface_get_data(source_surface);
unsigned char* dest_data = (unsigned char*)malloc(stride * h);
int i = 0;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
RGBA pixel = (RGBA){0, 0, 0, 0};
int cnt = 0;
for (int dx = -BLUR; dx <= BLUR; ++dx) {
for (int dy = -BLUR; dy <= BLUR; ++dy) {
if (x + dx >= 0 && x + dx < w && y + dy >= 0 && y + dy < h) {
RGBA neighbour_pixel = read_pixel(w, h, source_data, x + dx, y + dy);
add_pixel(pixel, neighbour_pixel);
++cnt;
}
}
}
scale_pixel(pixel, 1.0 / cnt);
write_pixel(w, h, dest_data, x, y, pixel);
}
}
cout << "Blurred image " << w << "x" << h << " with stride " << stride << endl;
cairo_surface_t* dest_surface = cairo_image_surface_create_for_data(dest_data, source_fmt, w, h, stride);
cairo_surface_write_to_png(dest_surface, "dionyziz-blurred.png");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment