mirror of https://github.com/i3/i3lock.git
Implement blurring the image
Algorithm copied over from my pngblur projectpull/57/head
parent
bc06a6d83e
commit
711d10f48e
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef __JS_BLUR
|
||||
#define __JS_BLUR
|
||||
void blur_surface(cairo_surface_t *img, int kernel_size);
|
||||
#endif
|
17
i3lock.c
17
i3lock.c
|
@ -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) */
|
||||
|
|
Loading…
Reference in New Issue