#include #include #include #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; uint8_t red, green, blue; 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; red = kernel_op(r, kernel, i, j, input.width, input.height); green = kernel_op(g, kernel, i, j, input.width, input.height); blue = kernel_op(b, kernel, i, j, input.width, input.height); out.data[index * 3] = red; out.data[index * 3 + 1] = green; out.data[index * 3 + 2] = blue; } } //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 edge[9] = { -1, -1, -1, -1, 8, -1, -1, -1, -1, }; float eye[9] = { 0, 0, 0, 0, 1, 0, 0, 0, 0, }; float gauss[9] = { 1, 2, 1, 2, 4, 2, 1, 2, 1, }; for (int i = 0; i < 9; i++) gauss[i] /= 16; ppm_read("images/house_1.ppm", &img); Image out_img = image_convolution(img, edge); ppm_write("out1.ppm", &out_img); out_img = image_convolution(out_img, gauss); ppm_write("out2.ppm", &out_img); return 0; }