#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; 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; }