#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 } |
|
|
|
|
||||||||||||||||||||||||
|
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 }
|
|
|
Definition at line 92 of file paloptimize.c. Referenced by paletteOptimize(). |
1.3.2