Browse Source

blur

master
Martin Dørum 4 years ago
parent
commit
901e35116c
2 changed files with 161 additions and 16 deletions
  1. 2
    2
      Makefile
  2. 159
    14
      blurrerbox.c

+ 2
- 2
Makefile View File

@@ -1,5 +1,5 @@
CFLAGS += -fopenmp $(shell pkg-config --cflags libjpeg) -g -fsanitize=address
LDFLAGS += -fopenmp $(shell pkg-config --libs libjpeg) -fsanitize=address
CFLAGS += -fopenmp $(shell pkg-config --cflags libjpeg) -ffast-math -O3
LDFLAGS += -fopenmp $(shell pkg-config --libs libjpeg)

blurrerbox: blurrerbox.c


+ 159
- 14
blurrerbox.c View File

@@ -4,46 +4,192 @@
#include <jpeglib.h>
#include <omp.h>

static int blur_radius = 15;
static int blur_times = 5;

static void blur_h(
unsigned char *dest, unsigned char *src,
int stride, int width, int height, int radius) {
double coeff = 1.0 / (radius * 2 + 1);

#pragma omp parallel for
for (int i = 0; i < height; ++i) {
int iwidth = i * stride * 3;
double r_acc = 0.0;
double g_acc = 0.0;
double b_acc = 0.0;
for (int j = -radius; j < width; ++j) {
if (j - radius - 1 >= 0) {
int index = iwidth + (j - radius - 1) * 3;
r_acc -= coeff * src[index + 0];
g_acc -= coeff * src[index + 1];
b_acc -= coeff * src[index + 2];
}
if (j + radius < width) {
int index = iwidth + (j + radius) * 3;
r_acc += coeff * src[index + 0];
g_acc += coeff * src[index + 1];
b_acc += coeff * src[index + 2];
}
if (j < 0)
continue;
int index = iwidth + j * 3;
dest[index + 0] = r_acc + 0.5;
dest[index + 1] = g_acc + 0.5;
dest[index + 2] = b_acc + 0.5;
}
}
}

static void blur_v(
unsigned char *dest, unsigned char *src,
int stride, int width, int height, int radius) {
double coeff = 1.0 / (radius * 2 + 1);

#pragma omp parallel for
for (int j = 0; j < width; ++j) {
double r_acc = 0.0;
double g_acc = 0.0;
double b_acc = 0.0;
for (int i = -radius; i < height; ++i) {
if (i - radius - 1 >= 0) {
int index = (i - radius - 1) * stride * 3 + j * 3;
r_acc -= coeff * src[index + 0];
g_acc -= coeff * src[index + 1];
b_acc -= coeff * src[index + 2];
}
if (i + radius < height) {
int index = (i + radius) * stride * 3 + j * 3;
r_acc += coeff * src[index + 0];
g_acc += coeff * src[index + 1];
b_acc += coeff * src[index + 2];
}
if (i < 0)
continue;
int index = i * stride * 3 + j * 3;
dest[index + 0] = r_acc + 0.5;
dest[index + 1] = g_acc + 0.5;
dest[index + 2] = b_acc + 0.5;
}
}
}

static void blur_once(
unsigned char *dest, unsigned char *src, unsigned char *scratch,
int stride, int width, int height, int radius) {
blur_h(scratch, src, stride, width, height, radius);
blur_v(dest, scratch, stride, width, height, radius);
}

void blur_rect(
unsigned char *image, unsigned char *scratch, unsigned char *scratch2,
int stride, int x, int y, int w, int h, int radius, int times) {
if (w == 0 || h == 0)
return;

unsigned char *orig = image;
int idx = y * stride * 3 + x * 3;
for (int i = 0; i < times; ++i) {
blur_once(scratch + idx, image + idx, scratch2, stride, w, h, radius);
if (i != times - 1) {
unsigned char *tmp = image;
image = scratch;
scratch = tmp;
}
}

if (image != orig)
memcpy(scratch + idx, image + idx, stride * h * 3);
}

unsigned char *process_image(
unsigned char *input_image, int input_width, int input_height,
int desired_width, int desired_height) {
unsigned char *output = calloc(3, desired_width * desired_height);
unsigned char *output_image = calloc(3, desired_width * desired_height);

double scale_w = (double)desired_width / (double)input_width;
double scale_h = (double)desired_height / (double)input_height;
double scale;
printf("scales are %fx%f\n", scale_w, scale_h);
int rect_x, rect_y, rect_w, rect_h;
if (scale_w < scale_h) {
printf("too wide?\n");
if (scale_w < scale_h)
scale = scale_w;
} else {
printf("too tall?\n");
else
scale = scale_h;
}

rect_w = input_width * scale;
rect_h = input_height * scale;
rect_x = (desired_width - rect_w) / 2.0;
rect_y = (desired_height - rect_h) / 2.0;

printf("rect is %ix%i:%i,%i\n", rect_w, rect_h, rect_x, rect_y);

// Write main image
#pragma omp parallel for
for (int y = 0; y < rect_h; ++y) {
for (int x = 0; x < rect_w; ++x) {
int input_y = y / scale;
int input_x = x / scale;
int input_idx = input_y * input_width * 3 + input_x * 3;
int output_idx = (y + rect_y) * desired_width * 3 + (x + rect_x) * 3;
output[output_idx + 0] = input_image[input_idx + 0];
output[output_idx + 1] = input_image[input_idx + 1];
output[output_idx + 2] = input_image[input_idx + 2];
output_image[output_idx + 0] = input_image[input_idx + 0];
output_image[output_idx + 1] = input_image[input_idx + 1];
output_image[output_idx + 2] = input_image[input_idx + 2];
}
}

// Top/bottom
for (int y = 0; y < rect_y; ++y) {
for (int x = 0; x < rect_w; ++x) {
int input_idx = (y + rect_y) * desired_width * 3 + (x + rect_x) * 3;
int output_idx = y * desired_width * 3 + (x + rect_x) * 3;
output_image[output_idx + 0] = output_image[input_idx + 0];
output_image[output_idx + 1] = output_image[input_idx + 1];
output_image[output_idx + 2] = output_image[input_idx + 2];

input_idx = (y + rect_h) * desired_width * 3 + (x + rect_x) * 3;
output_idx = (y + rect_h + rect_y) * desired_width * 3 + (x + rect_x) * 3;
output_image[output_idx + 0] = output_image[input_idx + 0];
output_image[output_idx + 1] = output_image[input_idx + 1];
output_image[output_idx + 2] = output_image[input_idx + 2];
}
}

return output;
// Left/right
for (int x = 0; x < rect_x; ++x) {
for (int y = 0; y < rect_h; ++y) {
int input_idx_l = (y + rect_y) * desired_width * 3 + (x + rect_x) * 3;
int output_idx_l = y * desired_width * 3 + (x) * 3;
int input_idx_r = (y + rect_y) * desired_width * 3 + (x + rect_w) * 3;
int output_idx_r = y * desired_width * 3 + (x + rect_w + rect_x) * 3;

output_image[output_idx_l + 0] = output_image[input_idx_l + 0];
output_image[output_idx_l + 1] = output_image[input_idx_l + 1];
output_image[output_idx_l + 2] = output_image[input_idx_l + 2];

output_image[output_idx_r + 0] = output_image[input_idx_r + 0];
output_image[output_idx_r + 1] = output_image[input_idx_r + 1];
output_image[output_idx_r + 2] = output_image[input_idx_r + 2];
}
}

// Blur
unsigned char *scratch = calloc(3, desired_width * desired_height);
unsigned char *scratch2 = calloc(3, desired_width * desired_height);
blur_rect(
output_image, scratch, scratch2, desired_width,
0, 0, desired_width, rect_y, blur_radius, blur_times);
blur_rect(
output_image, scratch, scratch2, desired_width,
0, rect_y + rect_h, desired_width, rect_y, blur_radius, blur_times);
blur_rect(
output_image, scratch, scratch2, desired_width,
0, 0, rect_x, desired_height, blur_radius, blur_times);
blur_rect(
output_image, scratch, scratch2, desired_width,
rect_x + rect_w, 0, rect_x, desired_height, blur_radius, blur_times);
free(scratch);
free(scratch2);

return output_image;
}

unsigned char *read_jpg(FILE *in, int *width, int *height) {
@@ -85,7 +231,6 @@ void write_jpg(FILE *out, unsigned char *image, int width, int height) {
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, out);

printf("writing %ix%i\n", width, height);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;

Loading…
Cancel
Save