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
108
src/op_c.c
108
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
|
// 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
|
// Pre-shift everything to avoid using OT_Get and be faster.
|
||||||
// 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 !
|
|
||||||
// GIMP use only 6 bits for G and B components in this table.
|
// GIMP use only 6 bits for G and B components in this table.
|
||||||
rmin=c->rmax <<16; rmax=c->rmin << 16;
|
rmin=c->rmax << to->dec_r; rmax=c->rmin << to->dec_r;
|
||||||
vmin=c->vmax << 8; vmax=c->vmin << 8;
|
vmin=c->vmax << to->dec_g; vmax=c->vmin << to->dec_g;
|
||||||
bmin=c->bmax; bmax=c->bmin;
|
bmin=c->bmax << to->dec_b; bmax=c->bmin << to->dec_b;
|
||||||
c->occurences=0;
|
c->occurences=0;
|
||||||
|
|
||||||
// Unoptimized code kept here for documentation purpose because the optimized
|
// Unoptimized code kept here for documentation purpose because the optimized
|
||||||
// one is unreadable : run over the whole cluster and find the min and max,
|
// one is unreadable : run over the whole cluster and find the min and max,
|
||||||
// and count the occurences at the same time.
|
// and count the occurences at the same time.
|
||||||
/*
|
/*
|
||||||
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++)
|
for (b=c->bmin;b<=c->bmax;b++)
|
||||||
{
|
{
|
||||||
nbocc=to->table[r + g + b]; // OT_get
|
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
|
// area to seek for the next one. Start at the edges of the cluster and go to
|
||||||
// the center until we find a pixel.
|
// the center until we find a pixel.
|
||||||
|
|
||||||
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++)
|
for(b=c->bmin;b<=c->bmax;b++)
|
||||||
{
|
{
|
||||||
if(to->table[r + g + b]) // OT_get
|
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:
|
RMAX:
|
||||||
for(r=c->rmax<<16;r>=rmin;r-=1<<16)
|
for(r=c->rmax<<to->dec_r;r>=rmin;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++)
|
for(b=c->bmin;b<=c->bmax;b++)
|
||||||
{
|
{
|
||||||
if(to->table[r + g + b]) // OT_get
|
if(to->table[r + g + b]) // OT_get
|
||||||
@ -388,8 +385,8 @@ RMAX:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
VMIN:
|
VMIN:
|
||||||
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=rmin;r<=rmax;r+=1<<16)
|
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||||
for(b=c->bmin;b<=c->bmax;b++)
|
for(b=c->bmin;b<=c->bmax;b++)
|
||||||
{
|
{
|
||||||
if(to->table[r + g + b]) // OT_get
|
if(to->table[r + g + b]) // OT_get
|
||||||
@ -399,8 +396,8 @@ VMIN:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
VMAX:
|
VMAX:
|
||||||
for(g=c->vmax<<8;g>=vmin;g-=1<<8)
|
for(g=c->vmax<<to->dec_g;g>=vmin;g-=1<<to->dec_g)
|
||||||
for(r=rmin;r<=rmax;r+=1<<16)
|
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||||
for(b=c->bmin;b<=c->bmax;b++)
|
for(b=c->bmin;b<=c->bmax;b++)
|
||||||
{
|
{
|
||||||
if(to->table[r + g + b]) // OT_get
|
if(to->table[r + g + b]) // OT_get
|
||||||
@ -411,8 +408,8 @@ VMAX:
|
|||||||
}
|
}
|
||||||
BMIN:
|
BMIN:
|
||||||
for(b=c->bmin;b<=c->bmax;b++)
|
for(b=c->bmin;b<=c->bmax;b++)
|
||||||
for(r=rmin;r<=rmax;r+=1<<16)
|
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||||
for(g=vmin;g<=vmax;g+=1<<8)
|
for(g=vmin;g<=vmax;g+=1<<to->dec_g)
|
||||||
{
|
{
|
||||||
if(to->table[r + g + b]) // OT_get
|
if(to->table[r + g + b]) // OT_get
|
||||||
{
|
{
|
||||||
@ -422,8 +419,8 @@ BMIN:
|
|||||||
}
|
}
|
||||||
BMAX:
|
BMAX:
|
||||||
for(b=c->bmax;b>=bmin;b--)
|
for(b=c->bmax;b>=bmin;b--)
|
||||||
for(r=rmin;r<=rmax;r+=1<<16)
|
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||||
for(g=vmin;g<=vmax;g+=1<<8)
|
for(g=vmin;g<=vmax;g+=1<<to->dec_g)
|
||||||
{
|
{
|
||||||
if(to->table[r + g + b]) // OT_get
|
if(to->table[r + g + b]) // OT_get
|
||||||
{
|
{
|
||||||
@ -434,16 +431,16 @@ BMAX:
|
|||||||
ENDCRUSH:
|
ENDCRUSH:
|
||||||
// We still need to seek the internal part of the cluster to count pixels
|
// We still need to seek the internal part of the cluster to count pixels
|
||||||
// inside it
|
// inside it
|
||||||
for(r=rmin;r<=rmax;r+=1<<16)
|
for(r=rmin;r<=rmax;r+=1<<to->dec_r)
|
||||||
for(g=vmin;g<=vmax;g+=1<<8)
|
for(g=vmin;g<=vmax;g+=1<<to->dec_g)
|
||||||
for(b=bmin;b<=bmax;b++)
|
for(b=bmin;b<=bmax;b++)
|
||||||
{
|
{
|
||||||
c->occurences+=to->table[r + g + b]; // OT_get
|
c->occurences+=to->table[r + g + b]; // OT_get
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unshift the values and put them in the cluster info
|
// Unshift the values and put them in the cluster info
|
||||||
c->rmin=rmin>>16; c->rmax=rmax>>16;
|
c->rmin=rmin>>to->dec_r; c->rmax=rmax>>to->dec_r;
|
||||||
c->vmin=vmin>>8; c->vmax=vmax>>8;
|
c->vmin=vmin>>to->dec_g; c->vmax=vmax>>to->dec_g;
|
||||||
c->bmin=bmin; c->bmax=bmax;
|
c->bmin=bmin; c->bmax=bmax;
|
||||||
|
|
||||||
// Find the longest axis to know which way to split the cluster
|
// 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
|
if (hue == 0) // split on red
|
||||||
{
|
{
|
||||||
// Run over the cluster until we reach the requested number of pixels
|
// 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++)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r>>=16;
|
r>>=to->dec_r;
|
||||||
g>>=8;
|
g>>=to->dec_g;
|
||||||
|
|
||||||
// More than half of the cluster pixel have r = rmin. Ensure we split somewhere anyway.
|
// More than half of the cluster pixel have r = rmin. Ensure we split somewhere anyway.
|
||||||
if (r == c->rmin) r++;
|
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
|
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++)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r>>=16; g>>=8;
|
r>>=to->dec_r; g>>=to->dec_g;
|
||||||
|
|
||||||
if (g == c->vmin) 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 (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];
|
cumul+=to->table[r + g + b];
|
||||||
if (cumul>=limit)
|
if (cumul>=limit)
|
||||||
@ -658,7 +655,7 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r>>=16; g>>=8;
|
r>>=to->dec_r; g>>=to->dec_g;
|
||||||
|
|
||||||
if (b == c->bmin) b++;
|
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
|
/// Setup the first cluster before we start the operations
|
||||||
/// This one covers the full palette range
|
/// This one covers the full palette range
|
||||||
void CS_Init(T_Cluster_set * cs, T_Occurrence_table * to)
|
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,
|
// 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,
|
// 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.
|
// 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,
|
CT_set_trad(colorTree,current->Rmin, current->Gmin, current->Bmin,
|
||||||
current->Rmax, current->Vmax, current->Bmax, 0);
|
current->Rmax, current->Vmax, current->Bmax, 0, to);
|
||||||
|
|
||||||
// Split it
|
// Split it
|
||||||
if (current->data.cut.volume <= 1)
|
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
|
/// 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;
|
int index;
|
||||||
T_Cluster* current = cs->clusters;
|
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].G=current->data.pal.g;
|
||||||
palette[index].B=current->data.pal.b;
|
palette[index].B=current->data.pal.b;
|
||||||
|
|
||||||
CT_set(tc,current->Rmin, current->Gmin, current->Bmin,
|
CT_set_trad(tc,current->Rmin, current->Gmin, current->Bmin,
|
||||||
current->Rmax, current->Vmax, current->Bmax, index);
|
current->Rmax, current->Vmax, current->Bmax,
|
||||||
|
index, to);
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1126,7 +1141,7 @@ void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs)
|
|||||||
/// @param b Resolution for blue
|
/// @param b Resolution for blue
|
||||||
CT_Tree* Optimize_palette(T_Bitmap24B image, int size,
|
CT_Tree* Optimize_palette(T_Bitmap24B image, int size,
|
||||||
T_Components * palette, int r, int g, int b)
|
T_Components * palette, int r, int g, int b)
|
||||||
{
|
{
|
||||||
T_Occurrence_table * to;
|
T_Occurrence_table * to;
|
||||||
CT_Tree* tc;
|
CT_Tree* tc;
|
||||||
T_Cluster_set * cs;
|
T_Cluster_set * cs;
|
||||||
@ -1181,7 +1196,7 @@ CT_Tree* Optimize_palette(T_Bitmap24B image, int size,
|
|||||||
//CS_Check(cs);
|
//CS_Check(cs);
|
||||||
|
|
||||||
// And finally generate the conversion table to map RGB > pal. index
|
// 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_Check(cs);
|
||||||
|
|
||||||
CS_Delete(cs);
|
CS_Delete(cs);
|
||||||
@ -1372,10 +1387,11 @@ int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int
|
|||||||
// meilleure précision possible
|
// meilleure précision possible
|
||||||
for (ip=0;ip<(10*3);ip+=3)
|
for (ip=0;ip<(10*3);ip+=3)
|
||||||
{
|
{
|
||||||
table = Optimize_palette(source,width*height,palette,
|
table = Optimize_palette(source,width*height,palette,
|
||||||
precision_24b[ip], precision_24b[ip+1], precision_24b[ip+2]);
|
precision_24b[ip], precision_24b[ip+1], precision_24b[ip+2]);
|
||||||
if (table != NULL)
|
if (table != NULL) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table!=NULL)
|
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_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_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_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 //
|
//////////////////////////// Méthodes de gestion des ensembles de dégradés //
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user