diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..601c617 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + gcc -Wall -Wextra -Wpedantic -g reducer.c -o reduce -lm diff --git a/Makefile~ b/Makefile~ new file mode 100644 index 0000000..fcd7bf6 --- /dev/null +++ b/Makefile~ @@ -0,0 +1,2 @@ +all: + gcc -Wall -Wextra -Wpedantic -g reduce.c -o reduce -lm diff --git a/photo.bmp b/photo.bmp new file mode 100644 index 0000000..948fbd9 Binary files /dev/null and b/photo.bmp differ diff --git a/reducer.c b/reducer.c new file mode 100644 index 0000000..e9b7375 --- /dev/null +++ b/reducer.c @@ -0,0 +1,339 @@ +#include +#include +#include +#include +#include +#include + + +struct pixel { + uint8_t R; + uint8_t G; + uint8_t B; +}; +typedef struct pixel pixel; + +struct dpixel { + double R; + double G; + double B; +}; +typedef struct dpixel dpixel; + +dpixel dpixel_of_pixel(pixel p) +{ + return (dpixel){.R=(double)p.R, .G=(double)p.G, .B=(double)p.B}; +} + +pixel pixel_of_dpixel(dpixel p) +{ + return (pixel){.R=floor(p.R), .G=floor(p.G), .B=floor(p.B)}; +} + +struct image { + int height; + int width; + pixel** bitmap; +}; +typedef struct image image; + + +image* create_image(int height, int width) +{ + image* img = malloc(sizeof(image)); + img->height = height; + img->width = width; + + img->bitmap = malloc(sizeof(pixel*) * height); + for (int i=0; ibitmap[i] = malloc(sizeof(pixel) * width); + } + + return img; +} + +void destroy_image(image *img) +{ + for (int i=0; iheight; i++) + { + free(img->bitmap[i]); + } + free(img->bitmap); + free(img); +} + +int read_integer(FILE* file, int pos, int size) +{ + int n=0; + fseek(file, pos, SEEK_SET); + for (int i=0; ibitmap[height-1-i][j] = px; + //printf("%d,%d: %d\n", i, j, img->bitmap[height-1-i][j].R); + } + } + + fclose(file); + + return img; +} + +void fprintint(FILE *file, int N, int size) +{ + for (int i=0; i>(8*i))&255, file); + } +} + +void write_bmp(image *img, char *path) +{ + int height = img->height; + int width = img->width; + + FILE* file = fopen(path, "wb"); + + /* print header */ + fprintf(file, "BM"); + fseek(file, 0x0E, SEEK_SET); + fprintint(file, 40, 4); // header size + fprintint(file, width, 4); // width + fprintint(file, height, 4); // height + fprintint(file, 1, 2); // number of color planes + fprintint(file, 24, 2); // bits per pixel + fprintint(file, 0, 4); // compression + fprintint(file, width*height, 2); // bits per pixel + fprintint(file, 100, 4); // résolution horizontale + fprintint(file, 100, 4); // résolution verticale + fprintint(file, 0, 4); // nb de couleurs (0 => 2**n) + fprintint(file, 0, 4); // nb de couleurs importantes (ignoré) + + int offset = ftell(file); + fseek(file, 0x02, SEEK_SET); + fprintint(file, offset + width*height, 4); + fseek(file, 0x0A, SEEK_SET); + fprintint(file, offset, 4); + + fseek(file, offset, SEEK_SET); + + for (int i=0; ibitmap[height-1-i][j]; + //printf("(%d, %d, %d)\n", px.B, px.G, px.R); + fputc(px.B, file); + fputc(px.G, file); + fputc(px.R, file); + } + } + + fclose(file); +} + + +double distance(pixel px1, dpixel px2) +{ + double Dr = px2.R - (double)px1.R; + double Dg = px2.G - (double)px1.G; + double Db = px2.B - (double)px1.B; + return sqrt(Dr*Dr + Dg*Dg + Db*Db); +} + + +image* k_means_reduce(image* input, int k) +{ + int width = input->width; + int height = input->height; + + dpixel* centroids = malloc(sizeof(dpixel) * k); + long* counts = calloc(k, sizeof(long)); + + int** classes = malloc(sizeof(int*) * height); + for (int i=0; ibitmap[i][j]); + } + for (int i=0; i %ld); ", centroids[p].R, centroids[p].G, centroids[p].B, counts[p]); + } + printf("]\n"); + */ + + for (int i=0; ibitmap[i][j], centroids[p]) < distance(input->bitmap[i][j], centroids[kmin])) + { + kmin = p; + } + } + + if (classes[i][j] != kmin) + { + classes[i][j] = kmin; + changed = true; + } + //printf("%d ", classes[i][j]); + } + //printf("\n"); + } + + // maintenant il faut recalculer les centroides selon les barycentres + for (int p=0; pbitmap[i][j].R; + centroids[c].G += (double)input->bitmap[i][j].G; + centroids[c].B += (double)input->bitmap[i][j].B; + } + } + + for (int p=0; pbitmap[i][j] = pixel_of_dpixel(centroids[classes[i][j]]); + } + } + + free(counts); + + free(centroids); + + for (int i=0; i \n", argv[0]); + exit(1); + } + int k = strtol(argv[3], NULL, 10); + + srand(time(NULL)); + + image *img = load_bmp(argv[1]); + + image *reduce = k_means_reduce(img, k); + write_bmp(reduce, argv[2]); + + destroy_image(img); + destroy_image(reduce); + + return 0; +}