static int k_means(Pixel *pixelData, uint32_t nPixels, Pixel *paletteData, uint32_t nPaletteEntries, uint32_t *qp, int threshold) { uint32_t *avg[3]; uint32_t *count; uint32_t i; uint32_t *avgDist; uint32_t **avgDistSortKey; int changes; int built=0; if (nPaletteEntries > UINT32_MAX / (sizeof(uint32_t))) { return 0; } /* malloc check ok, using calloc */ if (!(count=calloc(nPaletteEntries, sizeof(uint32_t)))) { return 0; } for(i=0;i<3;i++) { avg[i]=NULL; } for(i=0;i<3;i++) { /* malloc check ok, using calloc */ if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) { goto error_1; } } /* this is enough of a check, since the multiplication n*size is done above */ if (nPaletteEntries > UINT32_MAX / nPaletteEntries) { goto error_1; } /* malloc check ok, using calloc, checking n*n above */ avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t)); if (!avgDist) { goto error_1; } /* malloc check ok, using calloc, checking n*n above */ avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *)); if (!avgDistSortKey) { goto error_2; } #ifndef NO_OUTPUT printf("[");fflush(stdout); #endif while (1) { if (!built) { compute_palette_from_quantized_pixels(pixelData,nPixels,paletteData,nPaletteEntries,avg,count,qp); build_distance_tables(avgDist,avgDistSortKey,paletteData,nPaletteEntries); built=1; } else { recompute_palette_from_averages(paletteData,nPaletteEntries,avg,count); resort_distance_tables(avgDist,avgDistSortKey,paletteData,nPaletteEntries); } changes=map_image_pixels_from_quantized_pixels(pixelData, nPixels, paletteData, nPaletteEntries, avgDist, avgDistSortKey, qp, avg, count); if (changes<0) { goto error_3; } #ifndef NO_OUTPUT printf (".(%d)",changes);fflush(stdout); #endif if (changes<=threshold) break; } #ifndef NO_OUTPUT printf("]\n"); #endif if (avgDistSortKey) free(avgDistSortKey); if (avgDist) free(avgDist); for(i=0;i<3;i++) if (avg[i]) free (avg[i]); if (count) free(count); return 1; error_3: if (avgDistSortKey) free(avgDistSortKey); error_2: if (avgDist) free(avgDist); error_1: for(i=0;i<3;i++) if (avg[i]) free (avg[i]); if (count) free(count); return 0; }
static int k_means(Pixel *pixelData, unsigned long nPixels, Pixel *paletteData, unsigned long nPaletteEntries, unsigned long *qp, int threshold) { unsigned long *avg[3]; unsigned long *count; unsigned long i; unsigned long *avgDist; unsigned long **avgDistSortKey; int changes; int built=0; if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) { return 0; } for(i=0;i<3;i++) { avg[i]=NULL; } for(i=0;i<3;i++) { if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) { goto error_1; } } avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries); if (!avgDist) { goto error_1; } avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries); if (!avgDistSortKey) { goto error_2; } #ifndef NO_OUTPUT printf("[");fflush(stdout); #endif while (1) { if (!built) { compute_palette_from_quantized_pixels(pixelData,nPixels,paletteData,nPaletteEntries,avg,count,qp); build_distance_tables(avgDist,avgDistSortKey,paletteData,nPaletteEntries); built=1; } else { recompute_palette_from_averages(paletteData,nPaletteEntries,avg,count); resort_distance_tables(avgDist,avgDistSortKey,paletteData,nPaletteEntries); } changes=map_image_pixels_from_quantized_pixels(pixelData, nPixels, paletteData, nPaletteEntries, avgDist, avgDistSortKey, qp, avg, count); if (changes<0) { goto error_3; } #ifndef NO_OUTPUT printf (".(%d)",changes);fflush(stdout); #endif if (changes<=threshold) break; } #ifndef NO_OUTPUT printf("]\n"); #endif if (avgDistSortKey) free(avgDistSortKey); if (avgDist) free(avgDist); for(i=0;i<3;i++) if (avg[i]) free (avg[i]); if (count) free(count); return 1; error_3: if (avgDistSortKey) free(avgDistSortKey); error_2: if (avgDist) free(avgDist); error_1: for(i=0;i<3;i++) if (avg[i]) free (avg[i]); if (count) free(count); return 0; }