Implement blurring the image

Algorithm copied over from my pngblur project
pull/57/head
Jakub 'beamerkun' Sokół 2016-01-30 15:34:30 +01:00
parent bc06a6d83e
commit 711d10f48e
3 changed files with 112 additions and 6 deletions

97
blur.c Normal file
View File

@ -0,0 +1,97 @@
#include <cairo.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "blur.h"
void _blur_bitmap(uint8_t bytes_per_pixel, uint8_t *source, uint8_t *result,
uint32_t width, uint32_t height, int ksize) {
uint32_t *temp;
int px;
temp = malloc(sizeof(uint32_t) * bytes_per_pixel * width * height);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
px = bytes_per_pixel * (x + width * y);
for (int i = 0; i < bytes_per_pixel; ++i) {
temp[px + i] = source[px + i];
if (x != 0)
temp[px + i] += temp[px - bytes_per_pixel + i];
if (y != 0)
temp[px + i] += temp[px - bytes_per_pixel * width + i];
if (x != 0 && y != 0)
temp[px + i] -= temp[px - bytes_per_pixel * (width + 1) + i];
}
}
}
double filter = (double)1 / (4 * ksize * ksize);
uint32_t t;
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int x_min, x_max, y_min, y_max;
if ((x_min = x - ksize) < 0)
x_min = 0;
if ((x_max = x + ksize) > width - 1)
x_max = width - 1;
if ((y_min = y - ksize) < 0)
y_min = 0;
if ((y_max = y + ksize) > height - 1)
y_max = height - 1;
px = bytes_per_pixel * (x + width * y);
for (int i = 0; i < bytes_per_pixel; ++i) {
t = temp[bytes_per_pixel * (x_min + width * y_min) + i];
t += temp[bytes_per_pixel * (x_max + width * y_max) + i];
t -= temp[bytes_per_pixel * (x_max + width * y_min) + i];
t -= temp[bytes_per_pixel * (x_min + width * y_max) + i];
t *= filter;
result[px + i] = t;
}
}
}
free(temp);
}
void blur_surface(cairo_surface_t *img, int kernel_size) {
unsigned char *data, *temp;
uint32_t width, height;
uint8_t bytes_per_pixel;
cairo_format_t pixel_format = cairo_image_surface_get_format(img);
width = cairo_image_surface_get_width(img);
height = cairo_image_surface_get_height(img);
data = cairo_image_surface_get_data(img);
switch (pixel_format) {
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
bytes_per_pixel = 4;
break;
default:
// We don't handle other formats
return;
}
temp = malloc(bytes_per_pixel * sizeof(uint8_t) * width * height);
cairo_surface_flush(img);
// 3 times would be enough, but doing it equal number of times so we
// get result in right buffer
_blur_bitmap(bytes_per_pixel, data, temp, width, height, kernel_size);
_blur_bitmap(bytes_per_pixel, temp, data, width, height, kernel_size);
_blur_bitmap(bytes_per_pixel, data, temp, width, height, kernel_size);
_blur_bitmap(bytes_per_pixel, temp, data, width, height, kernel_size);
cairo_surface_mark_dirty(img);
free(temp);
}

4
blur.h Normal file
View File

@ -0,0 +1,4 @@
#ifndef __JS_BLUR
#define __JS_BLUR
void blur_surface(cairo_surface_t *img, int kernel_size);
#endif

View File

@ -30,6 +30,7 @@
#include <cairo/cairo-xcb.h>
#include "i3lock.h"
#include "blur.h"
#include "xcb.h"
#include "cursors.h"
#include "unlock_indicator.h"
@ -66,7 +67,7 @@ extern unlock_state_t unlock_state;
extern pam_state_t pam_state;
int failed_attempts = 0;
bool show_failed_attempts = false;
bool blur = false;
int blur = 0;
static struct xkb_state *xkb_state;
static struct xkb_context *xkb_context;
@ -749,7 +750,7 @@ int main(int argc, char *argv[]) {
{"version", no_argument, NULL, 'v'},
{"nofork", no_argument, NULL, 'n'},
{"beep", no_argument, NULL, 'b'},
{"blur", no_argument, NULL, 0},
{"blur", required_argument, NULL, 0},
{"dpms", no_argument, NULL, 'd'},
{"color", required_argument, NULL, 'c'},
{"pointer", required_argument, NULL, 'p'},
@ -825,8 +826,12 @@ int main(int argc, char *argv[]) {
case 0:
if (strcmp(longopts[optind].name, "debug") == 0)
debug_mode = true;
if (strcmp(longopts[optind].name, "blur") == 0)
blur = true;
if (strcmp(longopts[optind].name, "blur") == 0) {
int kernel = 0;
if (sscanf(optarg, "%d", &kernel) != 1 || time < 0)
errx(EXIT_FAILURE, "invalid kernel size, it must be a positive integer\n");
blur = kernel;
}
break;
case 'f':
show_failed_attempts = true;
@ -938,8 +943,8 @@ int main(int argc, char *argv[]) {
}
}
if(blur && img != NULL) {
// blur handling goes here
if(blur > 0 && img != NULL) {
blur_surface(img, blur);
}
/* Pixmap on which the image is rendered to (if any) */