Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

palcreate.c

Go to the documentation of this file.
00001 /*}{*************************************************/
00002 
00003 /****************************************************************************************/
00004 /*  PalCreate                                                                           */
00005 /*                                                                                      */
00006 /*  Author: Charles Bloom                                                               */
00007 /*  Description:  Palette Creation code                                                 */
00008 /*                                                                                      */
00009 /*  The contents of this file are subject to the Genesis3D Public License               */
00010 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00011 /*  compliance with the License. You may obtain a copy of the License at                */
00012 /*  http://www.genesis3d.com                                                            */
00013 /*                                                                                      */
00014 /*  Software distributed under the License is distributed on an "AS IS"                 */
00015 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00016 /*  the License for the specific language governing rights and limitations              */
00017 /*  under the License.                                                                  */
00018 /*                                                                                      */
00019 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00020 /*Genesis3D Version 1.1 released November 15, 1999                            */
00021 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00022 /*                                                                                      */
00023 /****************************************************************************************/
00024 
00025 /**********
00026 
00027 createPalGood goes in about 0.8 seconds
00028 with about 0.5 of those in the "CreatePalOctTree" function
00029 
00030 // <> could use Optimize
00031 
00032 ---------------
00033 
00034 createPaletteFast :
00035         trivial kludge:
00036                 gather colors in an octree
00037                 sorts colors on popularity
00038                 adds them to the palette, trying to avoiding adding extremely similar colors
00039                 has some speed-ups (like croppping low-count leaves)
00040 
00041 createPaletteGood :
00042         this is the "optimal" octree color quantizer. (see below, note on non-optimality)
00043         it is *VERY FAST* !
00044         gather all colors in an octree
00045         prune isolated strands so all nodes have > 1 kids
00046         the primary action is a "collapse" move:
00047                 a leaf is cut, so that its color will be mapped to a sibling
00048                 if it has no siblings, the color gets mapped to its parent
00049         each leaf keeps track of the "cost" (= increase in MSE) of cutting it
00050         each node has color which is the weighted average of its children
00051         the "cost" of a node, is the cost of all its children, plus the cost to
00052                 move its new centroid.  This is exact, it's kind of subtle. see later
00053         we keep removing the node which has the lowest cost to cut
00054                 (we use a radix sort to sort on cutCost ; this gives us the speed win)
00055 
00056 my fast (incremental) way to compute the GE_TRUE node cost :
00057         GE_TRUE_cost = Sum[kids] kid_count * (kid_color - new_color)^2
00058         my_cost = Sum[kids] kid_count * (kid_color - node_color)^2
00059                                         + node_count * (node_color - new_color)^2
00060 
00061         GE_TRUE_cost = Sum[kids] kid_count * (kid_color - new_color)^2
00062                           = Sum[kids] kid_count * ((kid_color - node_color) + (node_color - new_color))^2
00063                           = Sum[kids] kid_count * ((kid_color - node_color)^2 + (node_color - new_color)^2
00064                                                                                 + 2 * (kid_color - node_color) * (node_color - new_color))
00065                         = approx_cost + 2 *  (node_color - new_color) * { Sum[kids] kid_count * (kid_color - node_color) }
00066                                           
00067         the correction here is exactly zero! why :
00068                 Sum[kids] kid_count * (kid_color - node_color) = (Sum[kids] kid_count * kid_color) - node_count * node_color = 0 !
00069         since that's the definition of node_color !
00070 
00071 why this isn't exactly optimal:
00072         because octree children without the same parent are never grouped.
00073         the classic example     is in the binary tree, values 128 and 127 should have a cost of 1 to be
00074                 merged together, but 128 will be merged with all values > 128 first.
00075         that is, the square boundaries of the tree are unnatural cuts in color space.
00076         this means that the "cutCost" is not accurate; there could be an actual lower MSE cost
00077                 than our cutCost.
00078         furthermore, cutCost should be relative to all other leaves, not to their parent nodes,
00079                 so that when I cut one leaf it changes the cutCosts of all other leaves.
00080 
00081 ***********/
00082 /*}{*************************************************/
00083 
00084 #include "palcreate.h"
00085 #include "tsc.h"
00086 #include "paloptimize.h"
00087 #include "ram.h"
00088 #include "yuv.h"
00089 #include "mempool.h"
00090 #include "utility.h"            // delete macro
00091 #include <stdlib.h>
00092 #include <assert.h>
00093 
00094 /*******/
00095 
00096 #define allocate(ptr)   ptr = geRam_AllocateClear(sizeof(*ptr))
00097 #define clear(ptr)              memset(ptr,0,sizeof(*ptr))
00098 
00099 /*}{*************************************************/
00100 
00101 geBitmap_Palette * createPaletteGood(const geBitmap_Info * Info,const void * Bits);
00102 geBitmap_Palette * createPaletteFast(const geBitmap_Info * Info,const void * Bits);
00103 
00104 paletteCreater myPaletteCreater = createPaletteGood;
00105 
00106 void setCreatePaletteFunc(paletteCreater func)
00107 {
00108         assert( func == createPaletteGood || func == createPaletteFast );
00109         myPaletteCreater = func;
00110 }
00111 
00112 geBitmap_Palette * createPalette(const geBitmap_Info * Info,const void * Bits)
00113 {
00114         assert(Info && Bits);
00115         switch(Info->Format)
00116         {
00117                 case GE_PIXELFORMAT_8BIT_PAL :
00118                         return Info->Palette;
00119                 case GE_PIXELFORMAT_8BIT_GRAY :
00120                 {
00121                 geBitmap_Palette * Pal;
00122                 uint8 GrayPal[256];
00123                 int i;
00124                         Pal = geBitmap_Palette_Create(GE_PIXELFORMAT_8BIT_GRAY,256);
00125                         if ( ! Pal ) return NULL;
00126                         for(i=0;i<256;i++) GrayPal[i] = i;
00127                         geBitmap_Palette_SetData(Pal,GrayPal,GE_PIXELFORMAT_8BIT_GRAY,256);
00128                 return Pal;
00129                 }
00130                 default:
00131                         return myPaletteCreater(Info,Bits);
00132         }
00133 }
00134 
00135 geBitmap_Palette * createPaletteFromBitmap(const geBitmap * Bitmap,geBoolean Optimize)
00136 {
00137 geBitmap * Lock;
00138 geBitmap_Info Info;
00139 const void * Bits;
00140 geBitmap_Palette * Pal;
00141 
00142         if ( ! geBitmap_GetInfo(Bitmap,&Info,NULL) )
00143                 return NULL;
00144 
00145         if ( ! geBitmap_LockForRead((geBitmap *)Bitmap,&Lock,0,0,GE_PIXELFORMAT_24BIT_RGB,GE_FALSE,0) )
00146                 return NULL;
00147         
00148         if ( ! geBitmap_GetInfo(Lock,&Info,NULL) )
00149                 return NULL;
00150 
00151         Bits = (const void *) geBitmap_GetBits(Lock);
00152 
00153         Pal = createPalette(&Info,Bits);
00154 
00155         if ( Pal && Optimize )
00156         {
00157         uint8 paldata[768];
00158 
00159                 if ( ! geBitmap_Palette_GetData(Pal,paldata,GE_PIXELFORMAT_24BIT_RGB,256) )
00160                         assert(0);
00161                 
00162                 paletteOptimize(&Info,Bits,paldata,256,0);
00163                 
00164                 if ( ! geBitmap_Palette_SetData(Pal,paldata,GE_PIXELFORMAT_24BIT_RGB,256) )
00165                         assert(0);
00166         }
00167                 
00168         geBitmap_UnLock(Lock);
00169 
00170 return Pal;
00171 }
00172 
00173 /*}{*************************************************/
00174 
00175 typedef struct octNode octNode;
00176 struct octNode 
00177 {
00178         octNode * kids[8];
00179         octNode * parent;
00180         int count,nKids;
00181         int R,G,B;
00182 
00183         // for the pruner:
00184         uint32 cutCost; // this could overflow in the upper root nodes
00185         octNode *prev,*next; // sorted linked list of leaves
00186 };
00187 
00188 #define square(x)       ((x)*(x))
00189 
00190 #define RGBbits(R,G,B,bits) (((((R)>>(bits))&1)<<2) + ((((G)>>(bits))&1)<<1) + (((B)>>((bits)))&1))
00191 
00192 #define RADIX_SIZE      1024
00193 
00194 int createOctTree(octNode * root,const geBitmap_Info * Info,const void * Bits,geBoolean doYUV);
00195 geBitmap_Palette * createPaletteGoodSub(const geBitmap_Info * Info,const void * Bits);
00196 void addOctNode(octNode *root,int R,int G,int B,int *nLeavesPtr);
00197 void gatherLeaves(octNode *node,octNode *** leavesPtrPtr,int minCount);
00198 void gatherLeavesCutting(octNode *node,octNode *** leavesPtrPtr);
00199 int leafCompareCount(const void *a,const void *b);
00200 int leafCompareCost(const void *a,const void *b);
00201 int findClosest(int R,int G,int B,uint8 *palette,int palEntries,int *foundPalPtr);
00202 void computeOctRGBs(octNode *node);
00203 void computeCutCosts(octNode *node);
00204 void readLeavesToPal(octNode **leaves,int gotLeaves,uint8 *palette,int palEntries);
00205 void insertRadix(octNode * radix,octNode *leaf);
00206 
00207 /*}{*************************************************/
00208 
00209 static MemPool * octNodePool = NULL;
00210 static int PoolRefs = 0;
00211 
00212 void PalCreate_Start(void)
00213 {
00214         if ( PoolRefs == 0 )
00215         {
00216         int num;
00217                 // we do addOctNode, one for each unique color
00218                 // make the poolhunks 64k
00219                 num = (1<<16) / sizeof(octNode);
00220                 octNodePool = MemPool_Create(sizeof(octNode),num,num);
00221                 assert(octNodePool);
00222         }
00223         PoolRefs ++;
00224 }
00225 
00226 void PalCreate_Stop(void)
00227 {
00228         PoolRefs --;
00229         if ( PoolRefs == 0 )
00230         {
00231                 MemPool_Destroy(&octNodePool);
00232         }
00233 }
00234 
00235 /*}{*************************************************/
00236 
00237 geBitmap_Palette * createPaletteFast(const geBitmap_Info * Info,const void * Bits)
00238 {
00239 octNode * root;
00240 int nLeaves,minCount,gotLeaves;
00241 octNode ** leaves,**leavesPtr;
00242 uint8 palette[768];
00243 int palEntries = 256;
00244 geBitmap_Palette * Pal;
00245 
00246         pushTSC();
00247 
00248         // read the whole image into an octree
00249         //      this is the only pass over the input plane
00250 
00251         MemPool_Reset(octNodePool);
00252         root = MemPool_GetHunk(octNodePool);
00253         assert(root);
00254         nLeaves = createOctTree(root,Info,Bits,GE_FALSE);
00255 
00256         leaves = geRam_AllocateClear(sizeof(octNode *)*nLeaves);
00257         assert(leaves);
00258         
00259         // gather leaves into a linear array
00260         //      for speed we ignore leaves with a count lower than [x]
00261 
00262         gotLeaves = 0;
00263         for( minCount = 3; minCount >= 0 && gotLeaves < palEntries ; minCount-- )
00264         {
00265                 leavesPtr = leaves;
00266                 gatherLeaves(root,&leavesPtr,minCount);
00267                 gotLeaves = ((uint32)leavesPtr - (uint32)leaves)/sizeof(octNode *);
00268         }
00269 
00270         // sort the leaves by count
00271 
00272         qsort(leaves,gotLeaves,sizeof(octNode *),leafCompareCount);
00273 
00274         // read the sorted leaves in by count; we try to only read in leaves
00275         //      that are farther than 'minDistance' from nodes already in the palette
00276 
00277         readLeavesToPal(leaves,gotLeaves,palette,palEntries);
00278 
00279         destroy(leaves);
00280 
00281         showPopTSC("createPalFast");
00282 
00283         Pal = geBitmap_Palette_Create(GE_PIXELFORMAT_24BIT_RGB,palEntries);
00284         if ( ! Pal )
00285                 return NULL;
00286         if ( ! geBitmap_Palette_SetData(Pal,palette,GE_PIXELFORMAT_24BIT_RGB,palEntries) )
00287                 assert(0);
00288 return Pal;
00289 }
00290 
00291 /*}{*************************************************/
00292 
00293 geBitmap_Palette * createPaletteGood(const geBitmap_Info * Info,const void * Bits)
00294 {
00295         return createPaletteGoodSub(Info,Bits);
00296 }
00297 
00298 geBitmap_Palette * createPaletteGoodSub(const geBitmap_Info * Info,const void * Bits)
00299 {
00300 octNode * root;
00301 int nLeaves,i,gotLeaves,radixN;
00302 octNode ** leaves,**leavesPtr;
00303 octNode *leaf,*node;
00304 octNode *radix;
00305 uint8 palette[768],*palPtr;
00306 int palEntries = 256;
00307 geBitmap_Palette * Pal;
00308 
00309         pushTSC();
00310 
00311         // read the whole image into an octree
00312         //      this is the only pass over the input plane
00313 
00314         MemPool_Reset(octNodePool);
00315         root = MemPool_GetHunk(octNodePool);
00316         assert(root);
00317 
00318         nLeaves = createOctTree(root,Info,Bits,GE_TRUE);
00319 
00320         leaves = geRam_AllocateClear(sizeof(octNode *)*nLeaves);
00321         assert(leaves);
00322 
00323         computeOctRGBs(root);
00324         root->parent = root;
00325         computeCutCosts(root);
00326         root->parent = NULL;
00327         
00328         // gather leaves into a linear array
00329         //      for speed we ignore leaves with a count lower than [x]
00330 
00331         leavesPtr = leaves;
00332         gatherLeavesCutting(root,&leavesPtr);
00333         gotLeaves = ((uint32)leavesPtr - (uint32)leaves)/sizeof(octNode *);
00334 
00335         // if gotLeaves < palEntries, just exit asap
00336         if ( gotLeaves < palEntries )
00337         {
00338                 readLeavesToPal(leaves,gotLeaves,palette,palEntries);
00339                 goto done;
00340         }
00341 
00342         // sort the leaves by cutCost
00343         // radix sort instead of qsort
00344 
00345         radix = geRam_AllocateClear(sizeof(octNode)*RADIX_SIZE);
00346         assert(radix);
00347 
00348         for(i=0;i<RADIX_SIZE;i++)
00349                 radix[i].next = radix[i].prev = &radix[i];
00350 
00351         for(i=0;i<gotLeaves;i++)
00352                 insertRadix(radix,leaves[i]);
00353 
00354         // keep cutting the tail
00355         radixN = 0;
00356         while(gotLeaves > palEntries)
00357         {
00358                 while( (leaf = radix[radixN].next) == &(radix[radixN]) )
00359                 {
00360                         radixN++;
00361                         assert( radixN < RADIX_SIZE );
00362                 }
00363                 // cut it
00364                 leaf->prev->next = leaf->next;
00365                 leaf->next->prev = leaf->prev;
00366 
00367                 node = leaf->parent;
00368                 assert(node);
00369                 node->nKids --;
00370 
00371                 // might turn its parent into a leaf;
00372                 // if so, add it to the list
00373                         // nKids no longer corresponds to the actual number of active kids
00374 
00375                 if ( node->nKids == 0 )
00376                         insertRadix(radix,node);
00377                 else
00378                         gotLeaves--;
00379         }
00380 
00381         // read the sorted leaves in by count; we try to only read in leaves
00382         //      that are farther than 'minDistance' from nodes already in the palette
00383 
00384         palPtr = palette;
00385         radixN = RADIX_SIZE-1;
00386         leaf = radix[radixN].prev;      
00387         for(i=0;i<palEntries && radixN>0;i++)
00388         {
00389                 *palPtr++ = leaf->R;
00390                 *palPtr++ = leaf->G;
00391                 *palPtr++ = leaf->B;
00392                 leaf = leaf->prev;
00393                 while ( leaf == &(radix[radixN]) )
00394                 {
00395                         radixN --;
00396                         if ( ! radixN )
00397                                 break;
00398                         leaf = radix[radixN].prev;
00399                 }
00400         }
00401 
00402         destroy(radix);
00403 
00404 done:
00405 
00406         destroy(leaves);
00407 
00408         showPopTSC("createPalGood");
00409 
00410         YUVb_to_RGBb_line(palette,palette,palEntries);
00411 
00412         Pal = geBitmap_Palette_Create(GE_PIXELFORMAT_24BIT_RGB,palEntries);
00413         if ( ! Pal )
00414                 return NULL;
00415 
00416         if ( ! geBitmap_Palette_SetData(Pal,palette,GE_PIXELFORMAT_24BIT_RGB,palEntries) )
00417                 assert(0);
00418 
00419 return Pal;
00420 }
00421 
00422 /*}{*************************************************/
00423 
00424 void insertRadix(octNode * radix,octNode *leaf)
00425 {
00426 octNode *insertAt;
00427 
00428         if ( leaf->cutCost >= RADIX_SIZE ) 
00429         {
00430                 octNode * head;
00431                 insertAt = head = & radix[RADIX_SIZE-1];
00432                 while(insertAt->cutCost < leaf->cutCost && insertAt->next != head )
00433                         insertAt = insertAt->next;
00434         }
00435         else
00436                 insertAt = & radix[leaf->cutCost];
00437 
00438         leaf->next = insertAt->next;
00439         leaf->next->prev = leaf;
00440         insertAt->next = leaf;
00441         insertAt->next->prev = insertAt;
00442 }
00443 
00444 int findClosest(int R,int G,int B,uint8 *palette,int palEntries,int *foundPalPtr)
00445 {
00446 int i,d,bestD,bestP;
00447         bestD = 99999999; bestP = -1;
00448         for(i=palEntries;i--;)
00449         {
00450                 d = square(R - palette[0]) + square(G - palette[1]) + square(B - palette[2]);
00451                 palette += 3;
00452                 if ( d < bestD ) 
00453                 {
00454                         bestD = d;
00455                         bestP = i;
00456                 }
00457         }
00458         if ( foundPalPtr ) *foundPalPtr = bestP;
00459 return bestD;
00460 }
00461 
00462 static void addOctNode(octNode *root,int R,int G,int B,int *nLeavesPtr)
00463 {
00464 int idx;
00465 int bits;
00466 octNode *node;
00467 
00468         node = root;
00469         for(bits=7;bits>=0;bits--) 
00470         {
00471                 idx = RGBbits(R,G,B,bits);
00472                 if ( ! node->kids[idx] ) 
00473                 {
00474                         node->nKids ++;
00475                         node->kids[idx] = MemPool_GetHunk(octNodePool);
00476                         node->kids[idx]->parent = node;
00477                 }
00478                 node->count ++;
00479                 node = node->kids[idx];
00480         }
00481         if ( node->count == 0 ) (*nLeavesPtr)++;
00482         node->count ++;
00483         node->R = R;
00484         node->G = G;
00485         node->B = B;
00486 }
00487 
00488 static void gatherLeaves(octNode *node,octNode *** leavesPtrPtr,int minCount)
00489 {
00490         if ( node->count <= minCount ) return;
00491         if ( node->nKids == 0 ) 
00492         {
00493                 *(*leavesPtrPtr)++ = node;      
00494         }
00495         else
00496         {
00497                 int i;
00498                 for(i=0;i<8;i++)
00499                 {
00500                         if ( node->kids[i] ) gatherLeaves(node->kids[i],leavesPtrPtr,minCount);
00501                 }
00502         }
00503 }
00504 
00505 static void gatherLeavesCutting(octNode *node,octNode *** leavesPtrPtr)
00506 {
00507         if ( node->nKids > 0 ) 
00508         {
00509                 int i;
00510                 for(i=0;i<8;i++)
00511                 {
00512                         if ( node->kids[i] )
00513                         {
00514                                 if ( node->kids[i]->count <= 1 || node->kids[i]->cutCost <= 1 )
00515                                 {
00516                                         //freeOctNodes(node->kids[i]);
00517                                         node->kids[i] = NULL;
00518                                         node->nKids--;
00519                                 }
00520                                 else
00521                                 {
00522                                         gatherLeavesCutting(node->kids[i],leavesPtrPtr);
00523                                         
00524                                         if ( node->kids[i]->nKids == 1 )
00525                                         {
00526                                                 octNode *kid;
00527                                                 int j;
00528                                                 kid = node->kids[i];
00529                                                 for(j=0;j<8;j++)
00530                                                         if ( kid->kids[j] ) 
00531                                                                 node->kids[i] = kid->kids[j];
00532                                                 assert( node->kids[i] != kid );
00533                                                 node->kids[i]->cutCost = kid->cutCost;
00534                                                 //destroy(kid);
00535                                                 node->kids[i]->parent = node;
00536                                         }
00537                                 }
00538                         }
00539                 }
00540         }
00541 
00542         if ( node->nKids == 0 ) 
00543         {
00544                 *(*leavesPtrPtr)++ = node;      
00545         }
00546 }
00547 
00548 static int leafCompareCount(const void *a,const void *b)
00549 {
00550 octNode *na,*nb;
00551         na = *((octNode **)a);
00552         nb = *((octNode **)b);
00553 return (nb->count) - (na->count);
00554 }
00555 static int leafCompareCost(const void *a,const void *b)
00556 {
00557 octNode *na,*nb;
00558         na = *((octNode **)a);
00559         nb = *((octNode **)b);
00560 return (nb->cutCost) - (na->cutCost);
00561 }
00562 
00563 void computeCutCosts(octNode *node)
00564 {
00565         assert(node->parent);
00566         node->cutCost = square(node->R - node->parent->R)
00567                                         + square(node->G - node->parent->G)
00568                                         + square(node->B - node->parent->B);
00569         node->cutCost *= node->count;
00570         
00571         if ( node->nKids > 0 )
00572         {
00573         int i;
00574                 for(i=0;i<8;i++)
00575                         if ( node->kids[i] )
00576                         {
00577                                 computeCutCosts(node->kids[i]);
00578                                 node->cutCost += node->kids[i]->cutCost;
00579                         }
00580         }
00581 }
00582 
00583 void computeOctRGBs(octNode *node)
00584 {
00585         if ( node->nKids > 0 )
00586         {
00587         int R,G,B;
00588         int i;
00589         octNode *kid;
00590                 R = G = B = 0;
00591                 for(i=0;i<8;i++)
00592                         if ( node->kids[i] )
00593                                 computeOctRGBs(node->kids[i]);
00594                 for(i=0;i<8;i++)
00595                 {
00596                         if ( kid = node->kids[i] )
00597                         {
00598                                 R += kid->count * kid->R;
00599                                 G += kid->count * kid->G;
00600                                 B += kid->count * kid->B;
00601                         }
00602                 }
00603                 node->R = R / (node->count);
00604                 node->G = G / (node->count);
00605                 node->B = B / (node->count);
00606         }
00607 }
00608 
00609 void readLeavesToPal(octNode **leaves,int gotLeaves,uint8 *palette,int palEntries)
00610 {
00611 octNode **leavesPtr;
00612 uint8 *palPtr;
00613 int R,G,B;
00614 int i,palGot;
00615 int distance,minDistance;
00616 
00617         palPtr = palette; palGot = 0;
00618         for(minDistance=256;minDistance>=0 && palGot < palEntries;minDistance>>=1)
00619         {
00620                 leavesPtr = leaves;
00621                 for(i=0;i<gotLeaves;i++)
00622                 {
00623                         R = (*leavesPtr)->R;
00624                         G = (*leavesPtr)->G;
00625                         B = (*leavesPtr)->B;
00626                         leavesPtr++;
00627                         distance = findClosest(R,G,B,palette,palGot,NULL);
00628                         if ( distance >= minDistance )
00629                         {
00630                                 *palPtr++ = R;
00631                                 *palPtr++ = G;
00632                                 *palPtr++ = B;
00633                                 palGot ++;
00634                                 if ( palGot == palEntries )
00635                                         break;
00636                         }
00637                 }
00638         }
00639 }
00640 
00641 /*}{*************************************************/
00642 
00643 int createOctTree(octNode * root,const geBitmap_Info * Info,const void * Bits,geBoolean doYUV)
00644 {
00645 int nLeaves;
00646 int w,h,xtra,bpp,x,y;
00647 gePixelFormat Format;
00648 const gePixelFormat_Operations * ops;
00649 int R,G,B,A;
00650 gePixelFormat_Decomposer Decompose;
00651 
00652         assert(Bits);
00653 
00654         nLeaves = 0;
00655 
00656         Format = Info->Format;
00657         w = Info->Width;
00658         h = Info->Height;
00659         xtra = Info->Stride - Info->Width;
00660         bpp = gePixelFormat_BytesPerPel(Format);
00661 
00662         ops = gePixelFormat_GetOperations(Format);
00663         assert(ops);
00664         Decompose = ops->DecomposePixel;
00665         assert(Decompose);
00666 
00667 //      pushTSC();
00668 
00669         if ( doYUV )
00670         {
00671                 switch(bpp)
00672                 {
00673                         default:
00674                         case 0:
00675                                 return GE_FALSE;
00676                         case 1:
00677                         {
00678                         const uint8 *ptr;
00679                                 ptr = Bits;
00680                                 for(y=h;y--;)
00681                                 {
00682                                         for(x=w;x--;)
00683                                         {
00684                                                 Decompose(*ptr++,&R,&G,&B,&A);
00685                                                 RGBi_to_YUVi(R,G,B,&R,&G,&B);
00686                                                 addOctNode(root,R,G,B,&nLeaves);
00687                                         }
00688                                         ptr += xtra;
00689                                 }
00690                                 break;
00691                         }
00692                         case 2:
00693                         {
00694                         const uint16 *ptr;
00695                         uint32 R,G,B,A;
00696                                 ptr = Bits;
00697                                 for(y=h;y--;)
00698                                 {
00699                                         for(x=w;x--;)
00700                                         {
00701                                                 Decompose(*ptr++,&R,&G,&B,&A);
00702                                                 RGBi_to_YUVi(R,G,B,&R,&G,&B);
00703                                                 addOctNode(root,R,G,B,&nLeaves);
00704                                         }
00705                                         ptr += xtra;
00706                                 }
00707                                 break;
00708                         }
00709 
00710                         case 3:
00711                         {
00712                         const uint8 *ptr;
00713                         uint32 R,G,B,A,Pixel;
00714 
00715                                 ptr = Bits;
00716                                 xtra *= 3;
00717 
00718                                 switch(Format)
00719                                 {
00720                                 case GE_PIXELFORMAT_24BIT_RGB :
00721                                         for(y=h;y--;)
00722                                         {
00723                                                 for(x=w;x--;)
00724                                                 {
00725                                                         RGBb_to_YUVi(ptr,&R,&G,&B);
00726                                                         ptr += 3;
00727                                                         addOctNode(root,R,G,B,&nLeaves);
00728                                                 }
00729                                                 ptr += xtra;
00730                                         }
00731                                         break;
00732                                 case GE_PIXELFORMAT_24BIT_BGR :
00733                                         for(y=h;y--;)
00734                                         {
00735                                                 for(x=w;x--;)
00736                                                 {
00737                                                         B = *ptr++;
00738                                                         G = *ptr++;
00739                                                         R = *ptr++;
00740                                                         RGBi_to_YUVi(R,G,B,&R,&G,&B);
00741                                                         addOctNode(root,R,G,B,&nLeaves);
00742                                                 }
00743                                                 ptr += xtra;
00744                                         }
00745                                         break;
00746                                 default:
00747                                         // can't get here now
00748                                         for(y=h;y--;)
00749                                         {
00750                                                 for(x=w;x--;)
00751                                                 {
00752                                                         Pixel = (ptr[0]<<16) + (ptr[1]<<8) + ptr[2]; ptr += 3;
00753                                                         Decompose(Pixel,&R,&G,&B,&A);
00754                                                         RGBi_to_YUVi(R,G,B,&R,&G,&B);
00755                                                         addOctNode(root,R,G,B,&nLeaves);
00756                                                 }
00757                                                 ptr += xtra;
00758                                         }
00759                                         break;
00760                                 }
00761                                 break;  // Thanks Bobtree
00762                         }
00763 
00764                         case 4:
00765                         {
00766                         const uint32 *ptr;
00767                         uint32 R,G,B,A;
00768                                 ptr = Bits;
00769                                 for(y=h;y--;)
00770                                 {
00771                                         for(x=w;x--;)
00772                                         {
00773                                                 Decompose(*ptr++,&R,&G,&B,&A);
00774                                                 RGBi_to_YUVi(R,G,B,&R,&G,&B);
00775                                                 addOctNode(root,R,G,B,&nLeaves);
00776                                         }
00777                                         ptr += xtra;
00778                                 }
00779                                 break;
00780                         }
00781                 }
00782         }
00783         else
00784         {
00785                 switch(bpp)
00786                 {
00787                         default:
00788                         case 0:
00789                                 return GE_FALSE;
00790                         case 1:
00791                         {
00792                         const uint8 *ptr;
00793                                 ptr = Bits;
00794                                 for(y=h;y--;)
00795                                 {
00796                                         for(x=w;x--;)
00797                                         {
00798                                                 Decompose(*ptr++,&R,&G,&B,&A);
00799                                                 addOctNode(root,R,G,B,&nLeaves);
00800                                         }
00801                                         ptr += xtra;
00802                                 }
00803                                 break;
00804                         }
00805                         case 2:
00806                         {
00807                         const uint16 *ptr;
00808                         uint32 R,G,B,A;
00809                                 ptr = Bits;
00810                                 for(y=h;y--;)
00811                                 {
00812                                         for(x=w;x--;)
00813                                         {
00814                                                 Decompose(*ptr++,&R,&G,&B,&A);
00815                                                 addOctNode(root,R,G,B,&nLeaves);
00816                                         }
00817                                         ptr += xtra;
00818                                 }
00819                                 break;
00820                         }
00821 
00822                         case 3:
00823                         {
00824                         const uint8 *ptr;
00825                         uint32 R,G,B,A,Pixel;
00826 
00827                                 ptr = Bits;
00828                                 xtra *= 3;
00829 
00830                                 switch(Format)
00831                                 {
00832                                 case GE_PIXELFORMAT_24BIT_RGB :
00833                                         for(y=h;y--;)
00834                                         {
00835                                                 for(x=w;x--;)
00836                                                 {
00837                                                         R = *ptr++;
00838                                                         G = *ptr++;
00839                                                         B = *ptr++;
00840                                                         addOctNode(root,R,G,B,&nLeaves);
00841                                                 }
00842                                                 ptr += xtra;
00843                                         }
00844                                         break;
00845                                 case GE_PIXELFORMAT_24BIT_BGR :
00846                                         for(y=h;y--;)
00847                                         {
00848                                                 for(x=w;x--;)
00849                                                 {
00850                                                         B = *ptr++;
00851                                                         G = *ptr++;
00852                                                         R = *ptr++;
00853                                                         addOctNode(root,R,G,B,&nLeaves);
00854                                                 }
00855                                                 ptr += xtra;
00856                                         }
00857                                         break;
00858                                 default:
00859                                         // can't get here now
00860                                         for(y=h;y--;)
00861                                         {
00862                                                 for(x=w;x--;)
00863                                                 {
00864                                                         Pixel = (ptr[0]<<16) + (ptr[1]<<8) + ptr[2]; ptr += 3;
00865                                                         Decompose(Pixel,&R,&G,&B,&A);
00866                                                         addOctNode(root,R,G,B,&nLeaves);
00867                                                 }
00868                                                 ptr += xtra;
00869                                         }
00870                                         break;
00871                                 }
00872                                 break;          // Thanks Bobtree
00873                         }
00874 
00875                         case 4:
00876                         {
00877                         const uint32 *ptr;
00878                         uint32 R,G,B,A;
00879                                 ptr = Bits;
00880                                 for(y=h;y--;)
00881                                 {
00882                                         for(x=w;x--;)
00883                                         {
00884                                                 Decompose(*ptr++,&R,&G,&B,&A);
00885                                                 addOctNode(root,R,G,B,&nLeaves);
00886                                         }
00887                                         ptr += xtra;
00888                                 }
00889                                 break;
00890                         }
00891                 }
00892         }
00893 
00894 //      showPopTSC("create Pal OctTree");
00895 
00896 return nLeaves;
00897 }
00898 
00899 /*}{*************************************************/

Generated on Tue Sep 30 12:36:03 2003 for GTestAndEngine by doxygen 1.3.2