#include #include #include #include #define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #include #include #include #include #include "scolor.h" unsigned char blend(unsigned char a, unsigned char b, float ratio){ return b * ratio + a * (1 - ratio); } unsigned char pix_average(unsigned char* pix){ int sum = pix[0]; sum += pix[1]; sum += pix[2]; return sum/3; } void apply_color(unsigned char* pix, unsigned char r, unsigned char g, unsigned char b){ pix[0] = r; pix[1] = g; pix[2] = b; } unsigned char mortar_threshold = 160; size_t array_length; unsigned char *image, *output; int width, height; char ismortarcolor(unsigned char* pix){ if(pix < image) return 0; if(pix > (image + array_length)) return 0; return pix[0] > mortar_threshold && pix[1] > mortar_threshold && pix[2] > mortar_threshold; } struct limits { size_t start; size_t stop; }; void* apply_filter(void* p){ struct limits *l = p; printf("Starting at %lu, stopping at %lu\n", l->start, l->stop); for(size_t i = l->start; i < l->stop; i += 3){ if(ismortarcolor(image + i)) { char neighbors[4] = { ismortarcolor(image + (i - 45)), ismortarcolor(image + (i + 45)), ismortarcolor(image + (i + width * 3 * 15)), ismortarcolor(image + (i - width * 3 * 15)) }; int sum = 0; for(int j = 0; j < 4; j++) sum += neighbors[j]; if(sum > 1){ output[i] = 30; output[i+ 2] = 30; } } output[i] = blend(output[i], pix_average(output + i), (float)i / array_length); output[i+1] = blend(output[i+1], pix_average(output + i), (float)i / array_length); output[i+2] = blend(output[i+2], pix_average(output + i), (float)i / array_length); } } double timediff(struct timeval* start, struct timeval* end) { double s_diff = end->tv_sec - start->tv_sec; double us_diff = end->tv_usec - start->tv_usec; s_diff += us_diff / 1000000; return s_diff; } int main(){ image = stbi_load("brick.jpg", &width, &height, 0, 3); array_length = width * height * 3; // 3 channels if(!image) puts(RED("No image, giving up!")); else printf(PURPLE("Image size: %d by %d\n"), width, height); output = malloc(array_length); memcpy(output, image, array_length); struct timeval start, end; gettimeofday(&start, NULL); int thread_count = 48; pthread_t threads[thread_count]; struct limits parameters[thread_count]; for(int i = 0; i < thread_count; i++){ parameters[i].start = i * (array_length / thread_count); parameters[i].stop = (i + 1) * (array_length / thread_count); pthread_create(&threads[i], 0, apply_filter, ¶meters[i]); } for(int i = 0; i < thread_count; i++){ pthread_join(threads[i], 0); } gettimeofday(&end, NULL); printf("Filter application time: %lf\n", timediff(&start, &end)); puts(GREEN("Done applying filter, saving image as done.png")); stbi_write_png("done.png", width, height, 3, output, 0); puts(GREEN("Saved image as done.png")); free(output); return 0; }