示例#1
0
文件: Quant.c 项目: Nexuapex/Pillow
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;
}
示例#2
0
文件: Quant.c 项目: Nexuapex/Pillow
int
quantize(Pixel *pixelData,
         uint32_t nPixels,
         uint32_t nQuantPixels,
         Pixel **palette,
         uint32_t *paletteLength,
         uint32_t **quantizedPixels,
         int kmeans)
{
   PixelList *hl[3];
   HashTable *h;
   BoxNode *root;
   uint32_t i;
   uint32_t *qp;
   uint32_t nPaletteEntries;

   uint32_t *avgDist;
   uint32_t **avgDistSortKey;
   Pixel *p;

#ifndef NO_OUTPUT
   uint32_t timer,timer2;
#endif

#ifndef NO_OUTPUT
   timer2=clock();
   printf ("create hash table..."); fflush(stdout); timer=clock();
#endif
   h=create_pixel_hash(pixelData,nPixels);
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif
   if (!h) {
      goto error_0;
   }

#ifndef NO_OUTPUT
   printf ("create lists from hash table..."); fflush(stdout); timer=clock();
#endif
   hl[0]=hl[1]=hl[2]=NULL;
   hashtable_foreach(h,hash_to_list,hl);
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif

   if (!hl[0]) {
      goto error_1;
   }

#ifndef NO_OUTPUT
   printf ("mergesort lists..."); fflush(stdout); timer=clock();
#endif
   for(i=0;i<3;i++) {
      hl[i]=mergesort_pixels(hl[i],i);
   }
#ifdef TEST_MERGESORT
   if (!test_sorted(hl)) {
      printf ("bug in mergesort\n");
      goto error_1;
   }
#endif
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif

#ifndef NO_OUTPUT
   printf ("median cut..."); fflush(stdout); timer=clock();
#endif
   root=median_cut(hl,nPixels,nQuantPixels);
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif
   if (!root) {
      goto error_1;
   }
   nPaletteEntries=0;
#ifndef NO_OUTPUT
   printf ("median cut tree to hash table..."); fflush(stdout); timer=clock();
#endif
   annotate_hash_table(root,h,&nPaletteEntries);
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif
#ifndef NO_OUTPUT
   printf ("compute palette...\n"); fflush(stdout); timer=clock();
#endif
   if (!compute_palette_from_median_cut(pixelData,nPixels,h,&p,nPaletteEntries)) {
      goto error_3;
   }
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif

   free_box_tree(root);
   root=NULL;

   /* malloc check ok, using calloc for overflow */
   qp=calloc(nPixels, sizeof(uint32_t));
   if (!qp) { goto error_4; }

   if (nPaletteEntries > UINT32_MAX / nPaletteEntries )  {
       goto error_5;
   }
   /* malloc check ok, using calloc for overflow, check of n*n above */
   avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t));
   if (!avgDist) { goto error_5; }

   /* malloc check ok, using calloc for overflow, check of n*n above */
   avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *));
   if (!avgDistSortKey) { goto error_6; }

   if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) {
      goto error_7;
   }

   if (!map_image_pixels_from_median_box(pixelData,nPixels,p,nPaletteEntries,h,avgDist,avgDistSortKey,qp)) {
      goto error_7;
   }

#ifdef TEST_NEAREST_NEIGHBOUR
#include <math.h>
   {
      uint32_t bestmatch,bestdist,dist;
      HashTable *h2;
      printf ("nearest neighbour search (full search)..."); fflush(stdout); timer=clock();
      h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
      for (i=0;i<nPixels;i++) {
         if (hashtable_lookup(h2,pixelData[i],&paletteEntry)) {
            bestmatch=paletteEntry;
         } else {
            bestmatch=0;
            bestdist=
               _SQR(pixelData[i].c.r-p[0].c.r)+
               _SQR(pixelData[i].c.g-p[0].c.g)+
               _SQR(pixelData[i].c.b-p[0].c.b);
            for (j=1;j<nPaletteEntries;j++) {
               dist=
                  _SQR(pixelData[i].c.r-p[j].c.r)+
                  _SQR(pixelData[i].c.g-p[j].c.g)+
                  _SQR(pixelData[i].c.b-p[j].c.b);
               if (dist==bestdist && j==qp[i]) {
                  bestmatch=j;
               }
               if (dist<bestdist) {
                  bestdist=dist;
                  bestmatch=j;
               }
            }
            hashtable_insert(h2,pixelData[i],bestmatch);
         }
         if (qp[i]!=bestmatch ) {
            printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n",
                    i,qp[i],bestmatch,
                    sqrt((double)(_SQR(pixelData[i].c.r-p[qp[i]].c.r)+
                                  _SQR(pixelData[i].c.g-p[qp[i]].c.g)+
                                  _SQR(pixelData[i].c.b-p[qp[i]].c.b))),
                    sqrt((double)(_SQR(pixelData[i].c.r-p[bestmatch].c.r)+
                                  _SQR(pixelData[i].c.g-p[bestmatch].c.g)+
                                  _SQR(pixelData[i].c.b-p[bestmatch].c.b)))
                   );
         }
      }
      hashtable_free(h2);
   }
#endif
#ifndef NO_OUTPUT
   printf ("k means...\n"); fflush(stdout); timer=clock();
#endif
   if (kmeans) k_means(pixelData,nPixels,p,nPaletteEntries,qp,kmeans-1);
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
#endif

   *quantizedPixels=qp;
   *palette=p;
   *paletteLength=nPaletteEntries;

#ifndef NO_OUTPUT
   printf ("cleanup..."); fflush(stdout); timer=clock();
#endif
   if (avgDist) free(avgDist);
   if (avgDistSortKey) free(avgDistSortKey);
   destroy_pixel_hash(h);
#ifndef NO_OUTPUT
   printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC);
   printf ("-----\ntotal time %f\n",(clock()-timer2)/(double)CLOCKS_PER_SEC);
#endif
   return 1;

error_7:
   if (avgDistSortKey) free(avgDistSortKey);
error_6:
   if (avgDist) free(avgDist);
error_5:
   if (qp) free(qp);
error_4:
   if (p) free(p);
error_3:
   if (root) free_box_tree(root);
error_1:
   destroy_pixel_hash(h);
error_0:
   *quantizedPixels=NULL;
   *paletteLength=0;
   *palette=NULL;
   return 0;
}
示例#3
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;
}