fix Optimize_palette() for precisions different than 8 8 8
do the right shifts instead of 16 / 8
This commit is contained in:
parent
4b0878c079
commit
d7179f7cba
100
src/op_c.c
100
src/op_c.c
@ -330,22 +330,19 @@ void Cluster_pack(T_Cluster * c,const T_Occurrence_table * const to)
|
||||
|
||||
// Find min. and max. values actually used for each component in this cluster
|
||||
|
||||
// Pre-shift everything to avoid using OT_Get and be faster. This will only
|
||||
// work if the occurence table actually has full precision, that is a
|
||||
// 256^3*sizeof(int) = 64MB table. If your computer has less free ram and
|
||||
// malloc fails, this will not work at all !
|
||||
// Pre-shift everything to avoid using OT_Get and be faster.
|
||||
// GIMP use only 6 bits for G and B components in this table.
|
||||
rmin=c->rmax <<16; rmax=c->rmin << 16;
|
||||
vmin=c->vmax << 8; vmax=c->vmin << 8;
|
||||
bmin=c->bmax; bmax=c->bmin;
|
||||
rmin=c->rmax << to->dec_r; rmax=c->rmin << to->dec_r;
|
||||
vmin=c->vmax << to->dec_g; vmax=c->vmin << to->dec_g;
|
||||
bmin=c->bmax << to->dec_b; bmax=c->bmin << to->dec_b;
|
||||
c->occurences=0;
|
||||
|
||||
// Unoptimized code kept here for documentation purpose because the optimized
|
||||
// one is unreadable : run over the whole cluster and find the min and max,
|
||||
// and count the occurences at the same time.
|
||||
/*
|
||||
for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16)
|
||||
for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
|
||||
for (r=c->rmin<<to->dec_r;r<=c->rmax<<to->dec_r;r+=1<<to->dec_r)
|
||||
for (g=c->vmin<<to->dec_g;g<=c->vmax<<to->dec_g;g+=1<<to->dec_g)
|
||||
for (b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
nbocc=to->table[r + g + b]; // OT_get
|
||||
@ -366,8 +363,8 @@ void Cluster_pack(T_Cluster * c,const T_Occurrence_table * const to)
|
||||
// area to seek for the next one. Start at the edges of the cluster and go to
|
||||
// the center until we find a pixel.
|
||||
|
||||
for(r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16)
|
||||
for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
|
||||
for(r=c->rmin<<to->dec_r;r<=c->rmax<<to->dec_r;r+=1<<to->dec_r)
|
||||
for(g=c->vmin<<to->dec_g;g<=c->vmax<<to->dec_g;g+=1<<to->dec_g)
|
||||
for(b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
if(to->table[r + g + b]) // OT_get
|
||||
@ -377,8 +374,8 @@ void Cluster_pack(T_Cluster * c,const T_Occurrence_table * const to)
|
||||
}
|
||||
}
|
||||
RMAX:
|
||||
for(r=c->rmax<<16;r>=rmin;r-=1<<16)
|
||||
for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
|
||||
for(r=c->rmax<<to->dec_r;r>=rmin;r-=1<<to->dec_r)
|
||||
for(g=c->vmin<<to->dec_g;g<=c->vmax<<to->dec_g;g+=1<<to->dec_g)
|
||||
for(b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
if(to->table[r + g + b]) // OT_get
|
||||
@ -388,8 +385,8 @@ RMAX:
|
||||
}
|
||||
}
|
||||
VMIN:
|
||||
for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
|
||||
for(r=rmin;r<=rmax;r+=1<<16)
|
||||
for(g=c->vmin<<to->dec_g;g<=c->vmax<<to->dec_g;g+=1<<to->dec_g)
|
||||
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||
for(b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
if(to->table[r + g + b]) // OT_get
|
||||
@ -399,8 +396,8 @@ VMIN:
|
||||
}
|
||||
}
|
||||
VMAX:
|
||||
for(g=c->vmax<<8;g>=vmin;g-=1<<8)
|
||||
for(r=rmin;r<=rmax;r+=1<<16)
|
||||
for(g=c->vmax<<to->dec_g;g>=vmin;g-=1<<to->dec_g)
|
||||
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||
for(b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
if(to->table[r + g + b]) // OT_get
|
||||
@ -411,8 +408,8 @@ VMAX:
|
||||
}
|
||||
BMIN:
|
||||
for(b=c->bmin;b<=c->bmax;b++)
|
||||
for(r=rmin;r<=rmax;r+=1<<16)
|
||||
for(g=vmin;g<=vmax;g+=1<<8)
|
||||
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||
for(g=vmin;g<=vmax;g+=1<<to->dec_g)
|
||||
{
|
||||
if(to->table[r + g + b]) // OT_get
|
||||
{
|
||||
@ -422,8 +419,8 @@ BMIN:
|
||||
}
|
||||
BMAX:
|
||||
for(b=c->bmax;b>=bmin;b--)
|
||||
for(r=rmin;r<=rmax;r+=1<<16)
|
||||
for(g=vmin;g<=vmax;g+=1<<8)
|
||||
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||
for(g=vmin;g<=vmax;g+=1<<to->dec_g)
|
||||
{
|
||||
if(to->table[r + g + b]) // OT_get
|
||||
{
|
||||
@ -434,16 +431,16 @@ BMAX:
|
||||
ENDCRUSH:
|
||||
// We still need to seek the internal part of the cluster to count pixels
|
||||
// inside it
|
||||
for(r=rmin;r<=rmax;r+=1<<16)
|
||||
for(g=vmin;g<=vmax;g+=1<<8)
|
||||
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||
for(g=vmin;g<=vmax;g+=1<<to->dec_g)
|
||||
for(b=bmin;b<=bmax;b++)
|
||||
{
|
||||
c->occurences+=to->table[r + g + b]; // OT_get
|
||||
}
|
||||
|
||||
// Unshift the values and put them in the cluster info
|
||||
c->rmin=rmin>>16; c->rmax=rmax>>16;
|
||||
c->vmin=vmin>>8; c->vmax=vmax>>8;
|
||||
c->rmin=rmin>>to->dec_r; c->rmax=rmax>>to->dec_r;
|
||||
c->vmin=vmin>>to->dec_g; c->vmax=vmax>>to->dec_g;
|
||||
c->bmin=bmin; c->bmax=bmax;
|
||||
|
||||
// Find the longest axis to know which way to split the cluster
|
||||
@ -562,9 +559,9 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
||||
if (hue == 0) // split on red
|
||||
{
|
||||
// Run over the cluster until we reach the requested number of pixels
|
||||
for (r = c->rmin<<16; r<=c->rmax<<16; r+=1<<16)
|
||||
for (r = c->rmin<<to->dec_r; r<=c->rmax<<to->dec_r; r+=1<<to->dec_r)
|
||||
{
|
||||
for (g = c->vmin<<8; g<=c->vmax<<8; g+=1<<8)
|
||||
for (g = c->vmin<<to->dec_g; g<=c->vmax<<to->dec_g; g+=1<<to->dec_g)
|
||||
{
|
||||
for (b = c->bmin; b<=c->bmax; b++)
|
||||
{
|
||||
@ -579,8 +576,8 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
||||
break;
|
||||
}
|
||||
|
||||
r>>=16;
|
||||
g>>=8;
|
||||
r>>=to->dec_r;
|
||||
g>>=to->dec_g;
|
||||
|
||||
// More than half of the cluster pixel have r = rmin. Ensure we split somewhere anyway.
|
||||
if (r == c->rmin) r++;
|
||||
@ -603,9 +600,9 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
||||
if (hue==1) // split on green
|
||||
{
|
||||
|
||||
for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
|
||||
for (g=c->vmin<<to->dec_g;g<=c->vmax<<to->dec_g;g+=1<<to->dec_g)
|
||||
{
|
||||
for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16)
|
||||
for (r=c->rmin<<to->dec_r;r<=c->rmax<<to->dec_r;r+=1<<to->dec_r)
|
||||
{
|
||||
for (b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
@ -620,7 +617,7 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
||||
break;
|
||||
}
|
||||
|
||||
r>>=16; g>>=8;
|
||||
r>>=to->dec_r; g>>=to->dec_g;
|
||||
|
||||
if (g == c->vmin) g++;
|
||||
|
||||
@ -643,9 +640,9 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
||||
|
||||
for (b=c->bmin;b<=c->bmax;b++)
|
||||
{
|
||||
for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
|
||||
for (g=c->vmin<<to->dec_g;g<=c->vmax<<to->dec_g;g+=1<<to->dec_g)
|
||||
{
|
||||
for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16)
|
||||
for (r=c->rmin<<to->dec_r;r<=c->rmax<<to->dec_r;r+=1<<to->dec_r)
|
||||
{
|
||||
cumul+=to->table[r + g + b];
|
||||
if (cumul>=limit)
|
||||
@ -658,7 +655,7 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
||||
break;
|
||||
}
|
||||
|
||||
r>>=16; g>>=8;
|
||||
r>>=to->dec_r; g>>=to->dec_g;
|
||||
|
||||
if (b == c->bmin) b++;
|
||||
|
||||
@ -741,6 +738,23 @@ void Cluster_Print(T_Cluster* node)
|
||||
}
|
||||
*/
|
||||
|
||||
// translate R G B values to 8 8 8
|
||||
void CT_set_trad(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin,
|
||||
byte Rmax, byte Gmax, byte Bmax, byte index, const T_Occurrence_table * to)
|
||||
{
|
||||
Rmin <<= to->red_r;
|
||||
Rmax <<= to->red_r;
|
||||
Rmax += ((1 << to->red_r) - 1);
|
||||
Gmin <<= to->red_g;
|
||||
Gmax <<= to->red_g;
|
||||
Gmax += ((1 << to->red_g) - 1);
|
||||
Bmin <<= to->red_b;
|
||||
Bmax <<= to->red_b;
|
||||
Bmax += ((1 << to->red_b) - 1);
|
||||
CT_set(colorTree, Rmin, Gmin, Bmin,
|
||||
Rmax, Gmax, Bmax, index);
|
||||
}
|
||||
|
||||
/// Setup the first cluster before we start the operations
|
||||
/// This one covers the full palette range
|
||||
void CS_Init(T_Cluster_set * cs, T_Occurrence_table * to)
|
||||
@ -870,8 +884,8 @@ void CS_Generate(T_Cluster_set * cs, const T_Occurrence_table * const to, CT_Tre
|
||||
// We are going to split this cluster, so add it to the color tree. It is a split cluster,
|
||||
// not a final one. We KNOW its two child will get added later (either because they are split,
|
||||
// or because they are part of the final cluster set). So, we add thiscluster with a NULL index.
|
||||
CT_set(colorTree,current->Rmin, current->Gmin, current->Bmin,
|
||||
current->Rmax, current->Vmax, current->Bmax, 0);
|
||||
CT_set_trad(colorTree,current->Rmin, current->Gmin, current->Bmin,
|
||||
current->Rmax, current->Vmax, current->Bmax, 0, to);
|
||||
|
||||
// Split it
|
||||
if (current->data.cut.volume <= 1)
|
||||
@ -988,7 +1002,7 @@ void CS_Sort_by_luminance(T_Cluster_set * cs)
|
||||
|
||||
|
||||
/// Generates the palette from the clusters, then the conversion table to map (RGB) to a palette index
|
||||
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Components * palette)
|
||||
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Components * palette, T_Occurrence_table * to)
|
||||
{
|
||||
int index;
|
||||
T_Cluster* current = cs->clusters;
|
||||
@ -999,8 +1013,9 @@ void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Compon
|
||||
palette[index].G=current->data.pal.g;
|
||||
palette[index].B=current->data.pal.b;
|
||||
|
||||
CT_set(tc,current->Rmin, current->Gmin, current->Bmin,
|
||||
current->Rmax, current->Vmax, current->Bmax, index);
|
||||
CT_set_trad(tc,current->Rmin, current->Gmin, current->Bmin,
|
||||
current->Rmax, current->Vmax, current->Bmax,
|
||||
index, to);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
@ -1181,7 +1196,7 @@ CT_Tree* Optimize_palette(T_Bitmap24B image, int size,
|
||||
//CS_Check(cs);
|
||||
|
||||
// And finally generate the conversion table to map RGB > pal. index
|
||||
CS_Generate_color_table_and_palette(cs, tc, palette);
|
||||
CS_Generate_color_table_and_palette(cs, tc, palette, to);
|
||||
//CS_Check(cs);
|
||||
|
||||
CS_Delete(cs);
|
||||
@ -1374,9 +1389,10 @@ int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int
|
||||
{
|
||||
table = Optimize_palette(source,width*height,palette,
|
||||
precision_24b[ip], precision_24b[ip+1], precision_24b[ip+2]);
|
||||
if (table != NULL)
|
||||
if (table != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (table!=NULL)
|
||||
{
|
||||
|
||||
@ -182,7 +182,7 @@ void CS_Get(T_Cluster_set * cs,T_Cluster ** c);
|
||||
void CS_Set(T_Cluster_set * cs,T_Cluster * c);
|
||||
void CS_Generate(T_Cluster_set * cs,const T_Occurrence_table * const to, CT_Tree* colorTree);
|
||||
void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to);
|
||||
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Components * palette);
|
||||
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Components * palette, T_Occurrence_table * to);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Méthodes de gestion des ensembles de dégradés //
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user