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