diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 117 | ||||
-rw-r--r-- | src/ppm.c | 2 |
2 files changed, 113 insertions, 6 deletions
@@ -1,16 +1,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; - ppm_read("images/boxes_1.ppm", &img); + float kernel[9] = { + -1, -1, -1, + -1, 8, -1, + -1, -1, -1, + }; - printf("width: %d\n", img.width); - printf("height: %d\n", img.height); - printf("bits: %d\n", img.pixel_bits); - printf("data[2]: %d\n", img.data[2]); + //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; } @@ -13,7 +13,7 @@ ppm_write(const char *file, Image *img) exit(1); } - size_t n_pixels; + size_t n_pixels = img->width * img->height * 3; fprintf(fp, "P6\n%d %d\n%d\n", img->width, img->height, img->pixel_bits); fwrite(img->data, n_pixels, sizeof(uint8_t), fp); |