aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
blob: 018232832290815e0b107a27bb8cc572e5f34760 (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "ppm.h"

static Image image_convolution(Image input, float kernel[9]);
static void split_rgb(Image input, uint8_t *r, uint8_t *g, uint8_t *b);
static void merge_rgb(Image *out, uint8_t *r, uint8_t *g, uint8_t *b);
static uint8_t kernel_op(uint8_t *data, float kernel[9], int i, int j, int w, int h);

Image
image_convolution(Image input, float kernel[9])
{
    Image out;
    out.width = input.width;
    out.height = input.height;
    out.pixel_bits = input.pixel_bits;

    size_t n_pixels = out.width * out.height * 3;

    out.data = calloc(n_pixels, sizeof(uint8_t));

    if (out.data == NULL) {
        perror("image_convolution() Error");
        exit(1);
    }

    uint8_t *r, *g, *b;
    r = calloc(input.width * input.height, sizeof(uint8_t));
    g = calloc(input.width * input.height, sizeof(uint8_t));
    b = calloc(input.width * input.height, sizeof(uint8_t));
    split_rgb(input, r, g, b);

    int i, j, index;
    for (i = 0; i < input.height; i++) {
        for (j = 0; j < input.width; j++) {
            index = i * input.width + j;
            r[index] = kernel_op(r, kernel, i, j, input.width, input.height);
            g[index] = kernel_op(g, kernel, i, j, input.width, input.height);
            b[index] = kernel_op(b, kernel, i, j, input.width, input.height);
        }
    }

    merge_rgb(&out, r, g, b);
    free(r);
    free(g);
    free(b);
    return out;
}

void
merge_rgb(Image *out, uint8_t *r, uint8_t *g, uint8_t *b)
{
    int i;
    for (i = 0; i < out->width * out->height; i++) {
        out->data[3 * i] = r[i];
        out->data[3 * i + 1] = g[i];
        out->data[3 * i + 2] = b[i];
    }
}

uint8_t
kernel_op(uint8_t *data, float kernel[9], int i, int j, int w, int h)
{
    float kernel_value = 0;
    int ki, kj, img_index, index_i, index_j, index_k;
    for (ki = 0; ki < 3; ki++) {
        for (kj = 0; kj < 3; kj++) {
            index_i = i + ki - 1; //height
            index_j = j + kj - 1; //width
            index_k = 3 * ki + kj;

            if (index_i < 0
                || index_i >= h
                || index_j < 0
                || index_j >= w)
                kernel_value += data[i * w + j] * kernel[index_k];
            else {
                img_index = index_i * w + index_j;
                kernel_value += data[img_index] * kernel[index_k];
            }

            kernel_value = (kernel_value > 255) ? 255: kernel_value;
            kernel_value = (kernel_value < 0) ? 0: kernel_value;
        }
    }
    return (uint8_t)kernel_value;
}

void
split_rgb(Image input, uint8_t *r, uint8_t *g, uint8_t *b)
{

    if (!r || !g || !b) {
        perror("rgb_split() Error");
        exit(1);
    }

    int i; 
    for (i = 0; i < input.width * input.height; i++) {
        r[i] = input.data[3 * i];
        g[i] = input.data[3 * i + 1];
        b[i] = input.data[3 * i + 2];
    }

}

int main(int argc, char *argv[])
{
    Image img;
    float kernel[9] = {
        -1, -1, -1,
        -1,  8, -1,
        -1, -1, -1,
    };

    //for (int i = 0;  i < 9; i++) kernel[i] /= 16;
    ppm_read("images/synth_1.ppm", &img);
    Image out_img = image_convolution(img, kernel);
    ppm_write("out.ppm", &out_img);
    return 0;
}
Feel free to download, copy and edit any repo