- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_quantizer.c

    00001 //-----------------------------------------------------------------------
    00002 //         Color Quantization Demo
    00003 //
    00004 // Author: Roman Podobedov
    00005 // Email: romka@ut.ee
    00006 // Romka Graphics: www.ut.ee/~romka
    00007 //
    00008 // Also in this file implemented Wu's Color Quantizer algorithm (v. 2)
    00009 // For details see Graphics Gems vol. II, pp. 126-133
    00010 //
    00011 // Wu's Color Quantizer Algorithm:
    00012 // Author: Xiaolin Wu
    00013 //                      Dept. of Computer Science
    00014 //                      Univ. of Western Ontario
    00015 //                      London, Ontario N6A 5B7
    00016 //                      wu@csd.uwo.ca
    00017 //                      http://www.csd.uwo.ca/faculty/wu/
    00018 //-----------------------------------------------------------------------
    00019
    00020 //-----------------------------------------------------------------------------
    00021 //
    00022 // ImageLib Sources
    00023 // by Denton Woods
    00024 // Last modified: 01/04/2009
    00025 //
    00026 // Filename: src-IL/src/il_quantizer.c
    00027 //
    00028 // Description:  Heavily modified by Denton Woods.
    00029 //
    00030 // 20040223 XIX : Modified so it works better with color requests < 256
    00031 // pallete always has memory space for 256 entries
    00032 // used so we can quant down to 255 colors then add a transparent color in there.
    00033 //
    00034 //-----------------------------------------------------------------------------
    00035
    00036 #include "il_internal.h"
    00037
    00038 #define MAXCOLOR        256
    00039 #define RED                     2
    00040 #define GREEN           1
    00041 #define BLUE            0
    00042
    00043 typedef struct Box
    00044 {
    00045     ILint r0;  // min value, exclusive
    00046     ILint r1;  // max value, inclusive
    00047     ILint g0;
    00048     ILint g1;
    00049     ILint b0;
    00050     ILint b1;
    00051     ILint vol;
    00052 } Box;
    00053
    00054 /* Histogram is in elements 1..HISTSIZE along each axis,
    00055  * element 0 is for base or marginal value
    00056  * NB: these must start out 0!
    00057  */
    00058
    00059 ILfloat         gm2[33][33][33];
    00060 ILint           wt[33][33][33], mr[33][33][33], mg[33][33][33], mb[33][33][33];
    00061 ILuint          size; //image size
    00062 ILint           K;    //colour look-up table size
    00063 ILushort        *Qadd;
    00064
    00065
    00066 ILint   WindW, WindH, WindD;
    00067 ILint   i;
    00068 ILubyte *buffer;
    00069 static ILint    Width, Height, Depth, Comp;
    00070 /*ILint TotalColors;
    00071 ILint   a, b;
    00072 ILubyte *buf1, *buf2;*/
    00073
    00074 ILuint n2(ILint s)
    00075 {
    00076         ILint   i;
    00077         ILint   res;
    00078
    00079         res = 1;
    00080         for (i = 0; i < s; i++) {
    00081                 res = res*2;
    00082         }
    00083
    00084         return res;
    00085 }
    00086
    00087
    00088 // Build 3-D color histogram of counts, r/g/b, c^2
    00089 ILboolean Hist3d(ILubyte *Ir, ILubyte *Ig, ILubyte *Ib, ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2)
    00090 {
    00091         ILint   ind, r, g, b;
    00092         ILint   inr, ing, inb, table[2560];
    00093         ILuint  i;
    00094
    00095         for (i = 0; i < 256; i++)
    00096         {
    00097                 table[i] = i * i;
    00098         }
    00099         Qadd = (ILushort*)ialloc(sizeof(ILushort) * size);
    00100         if (Qadd == NULL)
    00101         {
    00102                 return IL_FALSE;
    00103         }
    00104
    00105         imemclear(Qadd, sizeof(ILushort) * size);
    00106
    00107         for (i = 0; i < size; i++)
    00108         {
    00109             r = Ir[i]; g = Ig[i]; b = Ib[i];
    00110             inr = (r>>3) + 1;
    00111             ing = (g>>3) + 1;
    00112             inb = (b>>3) + 1;
    00113             Qadd[i] = ind = (inr<<10)+(inr<<6)+inr+(ing<<5)+ing+inb;
    00114             //[inr][ing][inb]
    00115             vwt[ind]++;
    00116             vmr[ind] += r;
    00117             vmg[ind] += g;
    00118             vmb[ind] += b;
    00119                 m2[ind] += (ILfloat)(table[r]+table[g]+table[b]);
    00120         }
    00121         return IL_TRUE;
    00122 }
    00123
    00124 /* At conclusion of the histogram step, we can interpret
    00125  *   wt[r][g][b] = sum over voxel of P(c)
    00126  *   mr[r][g][b] = sum over voxel of r*P(c)  ,  similarly for mg, mb
    00127  *   m2[r][g][b] = sum over voxel of c^2*P(c)
    00128  * Actually each of these should be divided by 'size' to give the usual
    00129  * interpretation of P() as ranging from 0 to 1, but we needn't do that here.
    00130  */
    00131
    00132 /* We now convert histogram into moments so that we can rapidly calculate
    00133  * the sums of the above quantities over any desired Box.
    00134  */
    00135
    00136
    00137 // Compute cumulative moments
    00138 void M3d(ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2)
    00139 {
    00140         ILushort        ind1, ind2;
    00141         ILubyte         i, r, g, b;
    00142         ILint           line, line_r, line_g, line_b, area[33], area_r[33], area_g[33], area_b[33];
    00143         ILfloat         line2, area2[33];
    00144
    00145         for (r = 1; r <= 32; r++) {
    00146                 for (i = 0; i <= 32; i++) {
    00147                         area2[i] = 0.0f;
    00148                         area[i]=area_r[i]=area_g[i]=area_b[i]=0;
    00149                 }
    00150                 for (g = 1; g <= 32; g++) {
    00151                         line2 = 0.0f;
    00152                         line = line_r = line_g = line_b = 0;
    00153                         for (b = 1; b <= 32; b++) {
    00154                                 ind1 = (r<<10) + (r<<6) + r + (g<<5) + g + b; // [r][g][b]
    00155                                 line += vwt[ind1];
    00156                                 line_r += vmr[ind1];
    00157                                 line_g += vmg[ind1];
    00158                                 line_b += vmb[ind1];
    00159                                 line2 += m2[ind1];
    00160                                 area[b] += line;
    00161                                 area_r[b] += line_r;
    00162                                 area_g[b] += line_g;
    00163                                 area_b[b] += line_b;
    00164                                 area2[b] += line2;
    00165                                 ind2 = ind1 - 1089; // [r-1][g][b]
    00166                                 vwt[ind1] = vwt[ind2] + area[b];
    00167                                 vmr[ind1] = vmr[ind2] + area_r[b];
    00168                                 vmg[ind1] = vmg[ind2] + area_g[b];
    00169                                 vmb[ind1] = vmb[ind2] + area_b[b];
    00170                                 m2[ind1] = m2[ind2] + area2[b];
    00171                         }
    00172                 }
    00173     }
    00174
    00175         return;
    00176 }
    00177
    00178
    00179 // Compute sum over a Box of any given statistic
    00180 ILint Vol(Box *cube, ILint mmt[33][33][33])
    00181 {
    00182     return( mmt[cube->r1][cube->g1][cube->b1]
    00183            -mmt[cube->r1][cube->g1][cube->b0]
    00184            -mmt[cube->r1][cube->g0][cube->b1]
    00185            +mmt[cube->r1][cube->g0][cube->b0]
    00186            -mmt[cube->r0][cube->g1][cube->b1]
    00187            +mmt[cube->r0][cube->g1][cube->b0]
    00188            +mmt[cube->r0][cube->g0][cube->b1]
    00189            -mmt[cube->r0][cube->g0][cube->b0] );
    00190 }
    00191
    00192 /* The next two routines allow a slightly more efficient calculation
    00193  * of Vol() for a proposed subBox of a given Box.  The sum of Top()
    00194  * and Bottom() is the Vol() of a subBox split in the given direction
    00195  * and with the specified new upper bound.
    00196  */
    00197
    00198 // Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1
    00199 //      (depending on dir)
    00200 ILint Bottom(Box *cube, ILubyte dir, ILint mmt[33][33][33])
    00201 {
    00202     switch(dir)
    00203     {
    00204                 case RED:
    00205                         return( -mmt[cube->r0][cube->g1][cube->b1]
    00206                                 +mmt[cube->r0][cube->g1][cube->b0]
    00207                                 +mmt[cube->r0][cube->g0][cube->b1]
    00208                                 -mmt[cube->r0][cube->g0][cube->b0] );
    00209                         break;
    00210                 case GREEN:
    00211                         return( -mmt[cube->r1][cube->g0][cube->b1]
    00212                                 +mmt[cube->r1][cube->g0][cube->b0]
    00213                                 +mmt[cube->r0][cube->g0][cube->b1]
    00214                                 -mmt[cube->r0][cube->g0][cube->b0] );
    00215                         break;
    00216                 case BLUE:
    00217                         return( -mmt[cube->r1][cube->g1][cube->b0]
    00218                                 +mmt[cube->r1][cube->g0][cube->b0]
    00219                                 +mmt[cube->r0][cube->g1][cube->b0]
    00220                                 -mmt[cube->r0][cube->g0][cube->b0] );
    00221                         break;
    00222     }
    00223     return 0;
    00224 }
    00225
    00226
    00227 // Compute remainder of Vol(cube, mmt), substituting pos for
    00228 //      r1, g1, or b1 (depending on dir)
    00229 ILint Top(Box *cube, ILubyte dir, ILint pos, ILint mmt[33][33][33])
    00230 {
    00231     switch (dir)
    00232     {
    00233                 case RED:
    00234                         return( mmt[pos][cube->g1][cube->b1]
    00235                            -mmt[pos][cube->g1][cube->b0]
    00236                            -mmt[pos][cube->g0][cube->b1]
    00237                            +mmt[pos][cube->g0][cube->b0] );
    00238                         break;
    00239                 case GREEN:
    00240                         return( mmt[cube->r1][pos][cube->b1]
    00241                            -mmt[cube->r1][pos][cube->b0]
    00242                            -mmt[cube->r0][pos][cube->b1]
    00243                            +mmt[cube->r0][pos][cube->b0] );
    00244                         break;
    00245                 case BLUE:
    00246                         return( mmt[cube->r1][cube->g1][pos]
    00247                            -mmt[cube->r1][cube->g0][pos]
    00248                            -mmt[cube->r0][cube->g1][pos]
    00249                            +mmt[cube->r0][cube->g0][pos] );
    00250                         break;
    00251     }
    00252
    00253     return 0;
    00254 }
    00255
    00256
    00257 // Compute the weighted variance of a Box
    00258 //      NB: as with the raw statistics, this is really the variance * size
    00259 ILfloat Var(Box *cube)
    00260 {
    00261         ILfloat dr, dg, db, xx;
    00262
    00263         dr = (ILfloat)Vol(cube, mr);
    00264         dg = (ILfloat)Vol(cube, mg);
    00265         db = (ILfloat)Vol(cube, mb);
    00266         xx = gm2[cube->r1][cube->g1][cube->b1]
    00267                 -gm2[cube->r1][cube->g1][cube->b0]
    00268                 -gm2[cube->r1][cube->g0][cube->b1]
    00269                 +gm2[cube->r1][cube->g0][cube->b0]
    00270                 -gm2[cube->r0][cube->g1][cube->b1]
    00271                 +gm2[cube->r0][cube->g1][cube->b0]
    00272                 +gm2[cube->r0][cube->g0][cube->b1]
    00273                 -gm2[cube->r0][cube->g0][cube->b0];
    00274
    00275         return xx - (dr*dr+dg*dg+db*db) / (ILfloat)Vol(cube, wt);
    00276 }
    00277
    00278 /* We want to minimize the sum of the variances of two subBoxes.
    00279  * The sum(c^2) terms can be ignored since their sum over both subBoxes
    00280  * is the same (the sum for the whole Box) no matter where we split.
    00281  * The remaining terms have a minus sign in the variance formula,
    00282  * so we drop the minus sign and MAXIMIZE the sum of the two terms.
    00283  */
    00284
    00285 ILfloat Maximize(Box *cube, ILubyte dir, ILint first, ILint last, ILint *cut,
    00286                                  ILint whole_r, ILint whole_g, ILint whole_b, ILint whole_w)
    00287 {
    00288         ILint   half_r, half_g, half_b, half_w;
    00289         ILint   base_r, base_g, base_b, base_w;
    00290         ILint   i;
    00291         ILfloat temp, max;
    00292
    00293         base_r = Bottom(cube, dir, mr);
    00294         base_g = Bottom(cube, dir, mg);
    00295         base_b = Bottom(cube, dir, mb);
    00296         base_w = Bottom(cube, dir, wt);
    00297         max = 0.0;
    00298         *cut = -1;
    00299
    00300         for (i = first; i < last; ++i) {
    00301                 half_r = base_r + Top(cube, dir, i, mr);
    00302                 half_g = base_g + Top(cube, dir, i, mg);
    00303                 half_b = base_b + Top(cube, dir, i, mb);
    00304                 half_w = base_w + Top(cube, dir, i, wt);
    00305                 // Now half_x is sum over lower half of Box, if split at i
    00306                 if (half_w == 0) {  // subBox could be empty of pixels!
    00307                         continue;       // never split into an empty Box
    00308                 }
    00309                 else {
    00310                         temp = ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g +
    00311                                         (ILfloat)half_b*half_b) / half_w;
    00312                 }
    00313
    00314                 half_r = whole_r - half_r;
    00315                 half_g = whole_g - half_g;
    00316                 half_b = whole_b - half_b;
    00317                 half_w = whole_w - half_w;
    00318                 if (half_w == 0) {  // subBox could be empty of pixels!
    00319                         continue;       // never split into an empty Box
    00320                 }
    00321                 else {
    00322                         temp += ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g +
    00323                                         (ILfloat)half_b*half_b) / half_w;
    00324                 }
    00325
    00326                 if (temp > max) {
    00327                         max = temp;
    00328                         *cut = i;
    00329                 }
    00330         }
    00331
    00332         return max;
    00333 }
    00334
    00335
    00336 ILint Cut(Box *set1, Box *set2)
    00337 {
    00338         ILubyte dir;
    00339         ILint cutr, cutg, cutb;
    00340         ILfloat maxr, maxg, maxb;
    00341         ILint whole_r, whole_g, whole_b, whole_w;
    00342
    00343         whole_r = Vol(set1, mr);
    00344         whole_g = Vol(set1, mg);
    00345         whole_b = Vol(set1, mb);
    00346         whole_w = Vol(set1, wt);
    00347
    00348         maxr = Maximize(set1, RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w);
    00349         maxg = Maximize(set1, GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w);
    00350         maxb = Maximize(set1, BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w);
    00351
    00352         if ((maxr >= maxg) && (maxr >= maxb)) {
    00353                 dir = RED;
    00354                 if (cutr < 0)
    00355                         return 0; // can't split the Box
    00356         }
    00357         else if ((maxg >= maxr) && (maxg >= maxb))
    00358                 dir = GREEN;
    00359         else
    00360                 dir = BLUE;
    00361
    00362         set2->r1 = set1->r1;
    00363         set2->g1 = set1->g1;
    00364         set2->b1 = set1->b1;
    00365
    00366         switch (dir)
    00367         {
    00368                 case RED:
    00369                         set2->r0 = set1->r1 = cutr;
    00370                         set2->g0 = set1->g0;
    00371                         set2->b0 = set1->b0;
    00372                         break;
    00373                 case GREEN:
    00374                         set2->g0 = set1->g1 = cutg;
    00375                         set2->r0 = set1->r0;
    00376                         set2->b0 = set1->b0;
    00377                         break;
    00378                 case BLUE:
    00379                         set2->b0 = set1->b1 = cutb;
    00380                         set2->r0 = set1->r0;
    00381                         set2->g0 = set1->g0;
    00382                         break;
    00383         }
    00384
    00385         set1->vol = (set1->r1-set1->r0) * (set1->g1-set1->g0) * (set1->b1-set1->b0);
    00386         set2->vol = (set2->r1-set2->r0) * (set2->g1-set2->g0) * (set2->b1-set2->b0);
    00387
    00388         return 1;
    00389 }
    00390
    00391
    00392 void Mark(struct Box *cube, int label, unsigned char *tag)
    00393 {
    00394         ILint r, g, b;
    00395
    00396         for (r = cube->r0 + 1; r <= cube->r1; r++) {
    00397                 for (g = cube->g0 + 1; g <= cube->g1; g++) {
    00398                         for (b = cube->b0 + 1; b <= cube->b1; b++) {
    00399                                 tag[(r<<10) + (r<<6) + r + (g<<5) + g + b] = label;
    00400                         }
    00401                 }
    00402         }
    00403         return;
    00404 }
    00405
    00406
    00407 ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols)
    00408 {
    00409         Box             cube[MAXCOLOR];
    00410         ILubyte *tag = NULL;
    00411         ILubyte lut_r[MAXCOLOR], lut_g[MAXCOLOR], lut_b[MAXCOLOR];
    00412         ILint   next;
    00413         ILint   weight;
    00414         ILuint  k;
    00415         ILfloat vv[MAXCOLOR], temp;
    00416         //ILint color_num;
    00417         ILubyte *NewData = NULL, *Palette = NULL;
    00418         ILimage *TempImage = NULL, *NewImage = NULL;
    00419         ILubyte *Ir = NULL, *Ig = NULL, *Ib = NULL;
    00420
    00421         ILint num_alloced_colors; // number of colors we allocated space for in palette, as NumCols but will not be less than 256
    00422
    00423         num_alloced_colors=NumCols;
    00424         if(num_alloced_colors<256) { num_alloced_colors=256; }
    00425
    00426
    00427         NewImage = iCurImage;
    00428         iCurImage = Image;
    00429         TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
    00430         iCurImage = NewImage;
    00431
    00432
    00433
    00434         if (TempImage == NULL)
    00435                 return NULL;
    00436
    00437         buffer = Image->Data;
    00438         WindW = Width = Image->Width;
    00439         WindH = Height = Image->Height;
    00440         WindD = Depth = Image->Depth;
    00441         Comp = Image->Bpp;
    00442         Qadd = NULL;
    00443
    00444         //color_num = ImagePrecalculate(Image);
    00445
    00446         NewData = (ILubyte*)ialloc(Image->Width * Image->Height * Image->Depth);
    00447         Palette = (ILubyte*)ialloc(3 * num_alloced_colors);
    00448         if (!NewData || !Palette) {
    00449                 ifree(NewData);
    00450                 ifree(Palette);
    00451                 return NULL;
    00452         }
    00453
    00454         Ir = (ILubyte*)ialloc(Width * Height * Depth);
    00455         Ig = (ILubyte*)ialloc(Width * Height * Depth);
    00456         Ib = (ILubyte*)ialloc(Width * Height * Depth);
    00457         if (!Ir || !Ig || !Ib) {
    00458                 ifree(Ir);
    00459                 ifree(Ig);
    00460                 ifree(Ib);
    00461                 ifree(NewData);
    00462                 ifree(Palette);
    00463                 return NULL;
    00464         }
    00465
    00466         size = Width * Height * Depth;
    00467
    00468         #ifdef ALTIVEC_GCC
    00469             register ILuint v_size = size>>4;
    00470             register ILuint pos = 0;
    00471             v_size = v_size /3;
    00472             register vector unsigned char d0,d1,d2;
    00473             register vector unsigned char red[3],blu[3],green[3];
    00474
    00475             register union{
    00476                 vector unsigned char vec;
    00477                 vector unsigned int load;
    00478             } mask_1, mask_2, mask_3;
    00479
    00480             mask_1.load = (vector unsigned int){0xFF0000FF,0x0000FF00,0x00FF0000,0xFF0000FF};
    00481             mask_2.load = (vector unsigned int){0x00FF0000,0xFF0000FF,0x0000FF00,0x00FF0000};
    00482             mask_2.load = (vector unsigned int){0x0000FF00,0x00FF0000,0xFF0000FF,0x0000FF00};
    00483
    00484             while( v_size >= 0 ) {
    00485                 d0 = vec_ld(pos,TempImage->Data);
    00486                 d1 = vec_ld(pos+16,TempImage->Data);
    00487                 d2 = vec_ld(pos+32,TempImage->Data);
    00488
    00489                 red[0] =   vec_and(d0,mask_1.vec);
    00490                 green[0] = vec_and(d0,mask_2.vec);
    00491                 blu[0] =   vec_and(d0,mask_3.vec);
    00492
    00493                 red[1] =   vec_and(d1,mask_3.vec);
    00494                 green[1] = vec_and(d1,mask_1.vec);
    00495                 blu[1] =   vec_and(d1,mask_2.vec);
    00496
    00497                 red[2] =   vec_and(d2,mask_2.vec);
    00498                 green[2] = vec_and(d2,mask_3.vec);
    00499                 blu[2] =   vec_and(d2,mask_1.vec);
    00500
    00501                 vec_st(red[0],pos,Ir);
    00502                 vec_st(red[1],pos+16,Ir);
    00503                 vec_st(red[2],pos+32,Ir);
    00504
    00505                 vec_st(blu[0],pos,Ib);
    00506                 vec_st(blu[1],pos+16,Ib);
    00507                 vec_st(blu[2],pos+32,Ib);
    00508
    00509                 vec_st(green[0],pos,Ig);
    00510                 vec_st(green[1],pos+16,Ig);
    00511                 vec_st(green[2],pos+32,Ig);
    00512
    00513                 pos += 48;
    00514             }
    00515             size -= pos;
    00516         #endif
    00517
    00518         for (k = 0; k < size; k++) {
    00519                 Ir[k] = TempImage->Data[k * 3];
    00520                 Ig[k] = TempImage->Data[k * 3 + 1];
    00521                 Ib[k] = TempImage->Data[k * 3 + 2];
    00522         }
    00523
    00524         #ifdef ALTIVEC_GCC
    00525            size = Width * Height * Depth;
    00526         #endif
    00527
    00528         // Set new colors number
    00529         K = NumCols;
    00530
    00531         if (K <= 256) {
    00532                 // Begin Wu's color quantization algorithm
    00533
    00534                 // May have "leftovers" from a previous run.
    00535
    00536                 imemclear(gm2, 33 * 33 * 33 * sizeof(ILfloat));
    00537                 imemclear(wt, 33 * 33 * 33 * sizeof(ILint));
    00538                 imemclear(mr, 33 * 33 * 33 * sizeof(ILint));
    00539                 imemclear(mg, 33 * 33 * 33 * sizeof(ILint));
    00540                 imemclear(mb, 33 * 33 * 33 * sizeof(ILint));
    00541
    00542                 if (!Hist3d(Ir, Ig, Ib, (ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2))
    00543                         goto error_label;
    00544
    00545                 M3d((ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2);
    00546
    00547                 cube[0].r0 = cube[0].g0 = cube[0].b0 = 0;
    00548                 cube[0].r1 = cube[0].g1 = cube[0].b1 = 32;
    00549                 next = 0;
    00550                 for (i = 1; i < K; ++i) {
    00551                         if (Cut(&cube[next], &cube[i])) { // volume test ensures we won't try to cut one-cell Box */
    00552                                 vv[next] = (cube[next].vol>1) ? Var(&cube[next]) : 0.0f;
    00553                                 vv[i] = (cube[i].vol>1) ? Var(&cube[i]) : 0.0f;
    00554                         }
    00555                         else {
    00556                                 vv[next] = 0.0;   // don't try to split this Box again
    00557                                 i--;              // didn't create Box i
    00558                         }
    00559                         next = 0;
    00560                         temp = vv[0];
    00561                         for (k = 1; (ILint)k <= i; ++k) {
    00562                                 if (vv[k] > temp) {
    00563                                         temp = vv[k]; next = k;
    00564                                 }
    00565                         }
    00566
    00567                         if (temp <= 0.0) {
    00568                                 K = i+1;
    00569                                 // Only got K Boxes
    00570                                 break;
    00571                         }
    00572                 }
    00573
    00574                 tag = (ILubyte*)ialloc(33 * 33 * 33 * sizeof(ILubyte));
    00575                 if (tag == NULL)
    00576                         goto error_label;
    00577                 for (k = 0; (ILint)k < K; k++) {
    00578                         Mark(&cube[k], k, tag);
    00579                         weight = Vol(&cube[k], wt);
    00580                         if (weight) {
    00581                                 lut_r[k] = (ILubyte)(Vol(&cube[k], mr) / weight);
    00582                                 lut_g[k] = (ILubyte)(Vol(&cube[k], mg) / weight);
    00583                                 lut_b[k] = (ILubyte)(Vol(&cube[k], mb) / weight);
    00584                         }
    00585                         else {
    00586                                 // Bogus Box
    00587                                 lut_r[k] = lut_g[k] = lut_b[k] = 0;
    00588                         }
    00589                 }
    00590
    00591                 for (i = 0; i < (ILint)size; i++) {
    00592                         NewData[i] = tag[Qadd[i]];
    00593                 }
    00594                 ifree(tag);
    00595                 ifree(Qadd);
    00596
    00597                 for (k = 0; k < NumCols; k++) {
    00598                         Palette[k * 3]     = lut_b[k];
    00599                         Palette[k * 3 + 1] = lut_g[k];
    00600                         Palette[k * 3 + 2] = lut_r[k];
    00601                 }
    00602         }
    00603         else { // If colors more than 256
    00604                 // Begin Octree quantization
    00605                 //Quant_Octree(Image->Width, Image->Height, Image->Bpp, buffer2, NewData, Palette, K);
    00606                 ilSetError(IL_INTERNAL_ERROR);  // Can't get much more specific than this.
    00607                 goto error_label;
    00608         }
    00609
    00610         ifree(Ig);
    00611         ifree(Ib);
    00612         ifree(Ir);
    00613         ilCloseImage(TempImage);
    00614
    00615         NewImage = (ILimage*)icalloc(sizeof(ILimage), 1);
    00616         if (NewImage == NULL) {
    00617                 return NULL;
    00618         }
    00619         ilCopyImageAttr(NewImage, Image);
    00620         NewImage->Bpp = 1;
    00621         NewImage->Bps = Image->Width;
    00622         NewImage->SizeOfPlane = NewImage->Bps * Image->Height;
    00623         NewImage->SizeOfData = NewImage->SizeOfPlane;
    00624         NewImage->Format = IL_COLOUR_INDEX;
    00625         NewImage->Type = IL_UNSIGNED_BYTE;
    00626
    00627         NewImage->Pal.Palette = Palette;
    00628         NewImage->Pal.PalSize = 256 * 3;
    00629         NewImage->Pal.PalType = IL_PAL_BGR24;
    00630         NewImage->Data = NewData;
    00631
    00632         return NewImage;
    00633
    00634 error_label:
    00635         ifree(NewData);
    00636         ifree(Palette);
    00637         ifree(Ig);
    00638         ifree(Ib);
    00639         ifree(Ir);
    00640         ifree(tag);
    00641         ifree(Qadd);
    00642         return NULL;
    00643 }