00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
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"
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
00184 uint32 cutCost;
00185 octNode *prev,*next;
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
00218
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
00249
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
00260
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
00271
00272 qsort(leaves,gotLeaves,sizeof(octNode *),leafCompareCount);
00273
00274
00275
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
00312
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
00329
00330
00331 leavesPtr = leaves;
00332 gatherLeavesCutting(root,&leavesPtr);
00333 gotLeaves = ((uint32)leavesPtr - (uint32)leaves)/sizeof(octNode *);
00334
00335
00336 if ( gotLeaves < palEntries )
00337 {
00338 readLeavesToPal(leaves,gotLeaves,palette,palEntries);
00339 goto done;
00340 }
00341
00342
00343
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
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
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
00372
00373
00374
00375 if ( node->nKids == 0 )
00376 insertRadix(radix,node);
00377 else
00378 gotLeaves--;
00379 }
00380
00381
00382
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
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
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
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
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;
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
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;
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
00895
00896 return nLeaves;
00897 }
00898
00899