-
Notifications
You must be signed in to change notification settings - Fork 1
/
convolute.c
84 lines (62 loc) · 1.91 KB
/
convolute.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <stdlib.h>
#include "farbfeld.h"
const float SHARPEN_KERNEL[3][3] = {
{ 0, -1, 0},
{-1, 5, -1},
{ 0, -1, 0},
};
const float BLUR_KERNEL[3][3] = {
{ 0.0625, 0.125, 0.0625 },
{ 0.1250, 0.250, 0.1250 },
{ 0.0625, 0.125, 0.0625 },
};
int convolve(const float kernel[3][3])
{
uint32_t width, height;
pixel_t* image = NULL;
read_header(&width, &height);
if (!(image = calloc(width * height, sizeof(pixel_t)))) {
perror("couldn't allocate memory");
return 1;
}
read_image(image, width, height);
write_header(width, height);
for (uint32_t y = 0; y < height; ++y) {
for (uint32_t x = 0; x < width; ++x) {
pixel_t accumulator = {0, 0, 0, PIXEL(image, x, y).a};
for (int ky = -1; ky < 2; ++ky) {
for (int kx = -1; kx < 2; ++kx) {
pixel_t* current = NULL;
float mult = kernel[kx + 1][ky + 1];
int idx = x + kx,
idy = y + ky;
if (idx < 0 || (uint32_t) idx >= width) idx = x;
if (idy < 0 || (uint32_t) idy >= height) idy = y;
current = PIXEL(&image, idx, idy);
accumulator.r += current->r * mult;
accumulator.g += current->g * mult;
accumulator.b += current->b * mult;
}
}
write_pixel(&accumulator);
}
}
return 0;
}
int main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "usage: %s KERNEL\n", argv[0]);
return 1;
}
const void *kernel = NULL;
if (!strcmp("blur", argv[1]))
kernel = &BLUR_KERNEL;
else if (!strcmp("sharpen", argv[1]))
kernel = &SHARPEN_KERNEL;
else {
fprintf(stderr, "unknown image kernel: %s\n", argv[1]);
return 1;
}
return convolve(kernel);
}