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

paloptimize.c File Reference

#include "yuv.h"
#include "palettize.h"
#include "utility.h"
#include "tsc.h"
#include "log.h"
#include "bitmap.h"
#include "pixelformat.h"

Go to the source code of this file.

Compounds

struct  palOptInfo

Defines

#define DIV(diff)   if ( diff < 0 ) diff = - ((-diff + 1)>>1); else if ( diff > 0 ) diff = ((diff + 1)>>1)

Functions

void paletteOptimize (const geBitmap_Info *BmInfo, const void *Bits, uint8 *palette, int palEntries, int maxSamples)

Variables

int stepTable [] = { 1009 , 757, 499, 401, 307, 239, 197, 157, 131, 103, 67, 41, 29, 17, 13, 7, 4, 1 }


Define Documentation

#define DIV diff   )     if ( diff < 0 ) diff = - ((-diff + 1)>>1); else if ( diff > 0 ) diff = ((diff + 1)>>1)
 


Function Documentation

void paletteOptimize const geBitmap_Info BmInfo,
const void *  Bits,
uint8 palette,
int  palEntries,
int  maxSamples
 

Definition at line 94 of file paloptimize.c.

References A, B, gePixelFormat_Operations::BytesPerPel, closestPal(), closestPalFree(), closestPalInit(), palOptInfo::count, geBitmap_Info::Format, G, gePixelFormat_ColorGetter, gePixelFormat_GetOperations(), gePixelFormat_Operations::GetColor, geBitmap_Info::Height, Log_Printf(), memclear, minmax, palInfo, pushTSC, R, showPopTSC, stepTable, geBitmap_Info::Stride, palOptInfo::totB, palOptInfo::totG, palOptInfo::totR, uint32, and uint8.

Referenced by createPaletteFromBitmap().

00095 {
00096 palInfo *palInfo;
00097 int pal,R,G,B,A;
00098 uint32 mse,last_mse;
00099 uint8 *palPtr;
00100 uint8 savePalette[768];
00101 int extraStepIndex,extraStepSize,extraStepSizeBytes=0,samples,totSamples;
00102 gePixelFormat_ColorGetter GetColor;
00103 const gePixelFormat_Operations * PixelOps;
00104 uint8 *ptr,*ptrEnd;
00105 int d;
00106 palOptInfo optInfo[256];
00107 
00108         assert(palEntries <= 256);
00109 
00110         pushTSC();
00111 
00112         // palette is 768 bytes
00113 
00114         R = palette[(palEntries-1)*3 + 0];
00115         G = palette[(palEntries-1)*3 + 1];
00116         B = palette[(palEntries-1)*3 + 2];
00117         for(pal=palEntries;pal<256;pal++)
00118         {
00119                 palette[pal*3 + 0] = R;
00120                 palette[pal*3 + 1] = G;
00121                 palette[pal*3 + 2] = B;
00122         }
00123 
00124         PixelOps = gePixelFormat_GetOperations(BmInfo->Format);
00125         GetColor = PixelOps->GetColor;
00126         ptrEnd = (uint8 *)Bits + BmInfo->Stride * BmInfo->Height * PixelOps->BytesPerPel;
00127 
00128         mse = ~(uint32)0;
00129         extraStepIndex = 0;
00130         extraStepSize = -1;
00131         totSamples = 0;
00132         if ( maxSamples <= 0 ) maxSamples = 0x0FFFFFFF;
00133         for(;;)
00134         {
00135                 if ( extraStepSize != 0 )
00136                 {
00137                         extraStepSize = ( stepTable[ extraStepIndex ] - 1 );
00138                         extraStepSizeBytes = extraStepSize * PixelOps->BytesPerPel;
00139                         extraStepIndex++;
00140                 }
00141 
00142                 last_mse = mse;
00143 
00144                 // <> this 'closestPal' is not great for this application
00145                 //              it's approximate & has a large initialization overhead
00146                 //       we should use the methods from the "Local K-Means" paper
00147 
00148                 palInfo = closestPalInit(palette);
00149                 if ( ! palInfo ) return;
00150 
00151                 memclear(optInfo,sizeof(palOptInfo)*palEntries);
00152 
00153                 mse = 0;
00154                 samples =0;
00155                 ptr = (uint8 *)Bits;
00156                 while( ptr < ptrEnd )
00157                 {
00158                         GetColor(&ptr,&R,&G,&B,&A);
00159 
00160                         pal = closestPal(R,G,B,palInfo);
00161 
00162                         if ( pal >= palEntries ) pal = palEntries-1;                    
00163                 
00164                         palPtr = palette + pal*3;
00165                         d = R - (*palPtr++);    mse += d*d;
00166                         d = G - (*palPtr++);    mse += d*d;
00167                         d = B - (*palPtr  );    mse += d*d;
00168 
00169                         optInfo[pal].totR += R;
00170                         optInfo[pal].totG += G;
00171                         optInfo[pal].totB += B;
00172                         optInfo[pal].count ++;
00173 
00174                         ptr += extraStepSizeBytes;
00175                         samples ++;
00176                 }
00177 
00178                 closestPalFree(palInfo);
00179 
00180                 if ( samples == 0 ) continue;
00181                 mse = (int)(((double)mse*256.0)/samples);
00182                 totSamples += samples;
00183 
00184                 if ( mse >= last_mse && extraStepSize == 0 )
00185                 {
00186                         memcpy(palette,savePalette,768);
00187                         mse = last_mse;
00188                         break;
00189                 }
00190                 else if ( mse > last_mse )
00191                 {
00192 #if 0
00193                         // seems to slow convergence (!?)
00194                         memcpy(palette,savePalette,768);
00195                         mse = last_mse;
00196 #endif
00197                 }
00198                 else
00199                 {
00200                         memcpy(savePalette,palette,768);
00201                 }
00202         
00203                 Log_Printf("mse*256 = %7d , extrastep = %4d, samples = %7d\n",mse,extraStepSize,samples);
00204 
00205                 if ( totSamples >= maxSamples )
00206                         break;
00207 
00208                 for(pal=0,palPtr = palette; pal<palEntries ; pal++,palPtr += 3)
00209                 {
00210                 double fd;
00211                 int diffR,diffG,diffB;
00212 
00213                         if ( optInfo[pal].count == 0 ) continue;
00214 
00215                         fd = 1.0 / optInfo[pal].count;
00216 
00217                         diffR = (int)(optInfo[pal].totR * fd) - palPtr[0];
00218                         diffG = (int)(optInfo[pal].totG * fd) - palPtr[1];
00219                         diffB = (int)(optInfo[pal].totB * fd) - palPtr[2];
00220 
00221 #if 1
00222                         #define DIV(diff)       if ( diff < 0 ) diff = - ((-diff + 1)>>1); else if ( diff > 0 ) diff = ((diff + 1)>>1)
00223                         DIV(diffR);
00224                         DIV(diffG);
00225                         DIV(diffB);
00226 #endif
00227 
00228 #if 0
00229                         // this helps sometimes, hurts sometimes
00230                         diffR = GaussianRand(diffR,abs(diffR));
00231                         diffG = GaussianRand(diffG,abs(diffG));
00232                         diffB = GaussianRand(diffB,abs(diffB));
00233 #endif
00234 
00235                         palPtr[0] = minmax( palPtr[0]+diffR , 0,255);
00236                         palPtr[1] = minmax( palPtr[1]+diffG , 0,255);
00237                         palPtr[2] = minmax( palPtr[2]+diffB , 0,255);
00238                 }
00239                 
00240                 if ( abs(mse - last_mse) < 50 && extraStepSize == 0 )
00241                 {
00242                         break;
00243                 }
00244         }
00245 
00246         showPopTSC("palOptimize");
00247 }


Variable Documentation

int stepTable[] = { 1009 , 757, 499, 401, 307, 239, 197, 157, 131, 103, 67, 41, 29, 17, 13, 7, 4, 1 }
 

Definition at line 92 of file paloptimize.c.

Referenced by paletteOptimize().


Generated on Tue Sep 30 12:37:50 2003 for GTestAndEngine by doxygen 1.3.2