* Fix issue with the color reduction: the node index was off by one, leading to a write out of the allocated memory, and, of course, strange crashes because of it.

* Add some const in function parameters, just to make sure.
 * Cleanup the comments, because I got lost in my own code...

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1881 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues 2011-12-30 23:12:14 +00:00
parent 48a3ccd54e
commit ee6ddf139b
3 changed files with 40 additions and 31 deletions

View File

@ -22,6 +22,7 @@
24bit RGB to 8bit indexed functions 24bit RGB to 8bit indexed functions
*/ */
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -40,9 +41,9 @@ CT_Tree* CT_new() {return calloc(1, sizeof(CT_Tree));}
/* /*
void CT_Print(CT_Node* node) void CT_Print(CT_Node* node)
{ {
printf("R %d %d\tG %d %d\tB %d %d\ti %d\n", printf("R %d %d\tG %d %d\tB %d %d\tc %d/%d\n",
node->Rmin, node->Rmax, node->Gmin, node->Gmax, node->Rmin, node->Rmax, node->Gmin, node->Gmax,
node->Bmin, node->Bmax, node->index); node->Bmin, node->Bmax, node->children[0], node->children[1]);
} }
*/ */
@ -51,7 +52,7 @@ void CT_set(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin,
{ {
CT_Node* parent; CT_Node* parent;
// Create and setup node // Create and setup node
CT_Node* node = &colorTree->nodes[++colorTree->nodecount]; CT_Node* node = &colorTree->nodes[colorTree->nodecount];
node->Rmin = Rmin; node->Rmin = Rmin;
node->Gmin = Gmin; node->Gmin = Gmin;
@ -61,9 +62,9 @@ void CT_set(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin,
node->Bmax = Bmax; node->Bmax = Bmax;
node->children[1] = index; node->children[1] = index;
// Now insert it in tree // Now insert it in tree (if we're not the root node)
parent = &colorTree->nodes[0]; parent = &colorTree->nodes[0];
if (parent != NULL) for(;;) { if (colorTree->nodecount != 0) for(;;) {
// Find where to insert ourselves // Find where to insert ourselves
// pre-condition: the parent we're looking at is a superset of the node we're inserting // pre-condition: the parent we're looking at is a superset of the node we're inserting
@ -76,6 +77,7 @@ void CT_set(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin,
if (parent->children[0] == 0) if (parent->children[0] == 0)
{ {
parent->children[0] = colorTree->nodecount; parent->children[0] = colorTree->nodecount;
// We KNOW children[1] was set to 0, because the parent was a split cluster.
break; break;
} else { } else {
CT_Node* child0 = &colorTree->nodes[parent->children[0]]; CT_Node* child0 = &colorTree->nodes[parent->children[0]];
@ -96,6 +98,8 @@ void CT_set(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin,
} }
} }
} }
++colorTree->nodecount;
} }
byte CT_get(CT_Tree* tree, byte r, byte g, byte b) byte CT_get(CT_Tree* tree, byte r, byte g, byte b)

View File

@ -219,8 +219,8 @@ T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b)
n->red_b=8-nbb_b; n->red_b=8-nbb_b;
// Allocate the table // Allocate the table
size=(n->rng_r)*(n->rng_g)*(n->rng_b)*sizeof(int); size=(n->rng_r)*(n->rng_g)*(n->rng_b);
n->table=(int *)calloc(size, 1); n->table=(int *)calloc(size, sizeof(int));
if (n->table == NULL) if (n->table == NULL)
{ {
// Not enough memory ! // Not enough memory !
@ -243,7 +243,7 @@ void OT_delete(T_Occurrence_table * t)
/// Get number of occurences for a given color /// Get number of occurences for a given color
int OT_get(T_Occurrence_table * t, int r, int g, int b) int OT_get(T_Occurrence_table * t, byte r, byte g, byte b)
{ {
int index; int index;
@ -254,7 +254,7 @@ int OT_get(T_Occurrence_table * t, int r, int g, int b)
/// Add 1 to the count for a color /// Add 1 to the count for a color
void OT_inc(T_Occurrence_table * t,int r,int g,int b) void OT_inc(T_Occurrence_table * t,byte r,byte g,byte b)
{ {
int index; int index;
@ -262,6 +262,7 @@ void OT_inc(T_Occurrence_table * t,int r,int g,int b)
r=(r>>t->red_r); r=(r>>t->red_r);
g=(g>>t->red_g); g=(g>>t->red_g);
b=(b>>t->red_b); b=(b>>t->red_b);
// Compute the address // Compute the address
index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b); index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b);
t->table[index]++; t->table[index]++;
@ -311,7 +312,7 @@ int OT_count_colors(T_Occurrence_table * t)
/// Pack a cluster, ie compute its {r,v,b}{min,max} values /// Pack a cluster, ie compute its {r,v,b}{min,max} values
void Cluster_pack(T_Cluster * c,T_Occurrence_table * to) void Cluster_pack(T_Cluster * c,const T_Occurrence_table * const to)
{ {
int rmin,rmax,vmin,vmax,bmin,bmax; int rmin,rmax,vmin,vmax,bmin,bmax;
int r,g,b; int r,g,b;
@ -475,7 +476,7 @@ ENDCRUSH:
/// Split a cluster on its longest axis. /// Split a cluster on its longest axis.
/// c = source cluster, c1, c2 = output after split /// c = source cluster, c1, c2 = output after split
void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue, void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
T_Occurrence_table * to) const T_Occurrence_table * const to)
{ {
int limit; int limit;
int cumul; int cumul;
@ -738,7 +739,7 @@ void CS_Get(T_Cluster_set * cs, T_Cluster ** c)
} }
/// Push a cluster in the list /// Push a copy of a cluster in the list
void CS_Set(T_Cluster_set * cs,T_Cluster * c) void CS_Set(T_Cluster_set * cs,T_Cluster * c)
{ {
T_Cluster* current = cs->clusters; T_Cluster* current = cs->clusters;
@ -773,11 +774,11 @@ void CS_Set(T_Cluster_set * cs,T_Cluster * c)
// 5) We take the box with the biggest number of pixels inside and we split it again // 5) We take the box with the biggest number of pixels inside and we split it again
// 6) Iterate until there are 256 boxes. Associate each of them to its middle color // 6) Iterate until there are 256 boxes. Associate each of them to its middle color
// At the same time, put the split clusters in the color tree for later palette lookup // At the same time, put the split clusters in the color tree for later palette lookup
void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to, CT_Tree* colorTree) void CS_Generate(T_Cluster_set * cs, const T_Occurrence_table * const to, CT_Tree* colorTree)
{ {
T_Cluster* current; T_Cluster* current;
T_Cluster* Nouveau1 = malloc(sizeof(T_Cluster)); T_Cluster Nouveau1;
T_Cluster* Nouveau2 = malloc(sizeof(T_Cluster)); T_Cluster Nouveau2;
// There are less than 256 boxes // There are less than 256 boxes
while (cs->nb<cs->nb_max) while (cs->nb<cs->nb_max)
@ -786,7 +787,9 @@ void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to, CT_Tree* colorTree
CS_Get(cs,&current); CS_Get(cs,&current);
//Cluster_Print(current); //Cluster_Print(current);
// We're going to split, so add the cluster to the colortree // 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, CT_set(colorTree,current->Rmin, current->Gmin, current->Bmin,
current->Rmax, current->Vmax, current->Bmax, 0); current->Rmax, current->Vmax, current->Bmax, 0);
@ -798,22 +801,22 @@ void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to, CT_Tree* colorTree
free(current); free(current);
break; break;
} }
Cluster_split(current, Nouveau1, Nouveau2, current->data.cut.plus_large, to); Cluster_split(current, &Nouveau1, &Nouveau2, current->data.cut.plus_large, to);
free(current); free(current);
// Pack the 2 new clusters (the split may leave some empty space between the // Pack the 2 new clusters (the split may leave some empty space between the
// box border and the first actual pixel) // box border and the first actual pixel)
Cluster_pack(Nouveau1, to); Cluster_pack(&Nouveau1, to);
Cluster_pack(Nouveau2, to); Cluster_pack(&Nouveau2, to);
// Put them back in the list // Put them back in the list
if (Nouveau1->occurences != 0) if (Nouveau1.occurences != 0)
CS_Set(cs,Nouveau1); CS_Set(cs,&Nouveau1);
if (Nouveau2->occurences != 0)
CS_Set(cs,Nouveau2);
if (Nouveau2.occurences != 0)
CS_Set(cs,&Nouveau2);
} }
} }
@ -822,9 +825,10 @@ void CS_Compute_colors(T_Cluster_set * cs, T_Occurrence_table * to)
{ {
T_Cluster * c; T_Cluster * c;
for (c=cs->clusters;c!=NULL;c=c->next) for (c=cs->clusters;c!=NULL;c=c->next) {
Cluster_compute_hue(c,to); Cluster_compute_hue(c,to);
} }
}
// We sort the clusters on two criterions to get a somewhat coherent palette. // We sort the clusters on two criterions to get a somewhat coherent palette.
@ -1023,6 +1027,7 @@ void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs)
/// Compute best palette for given picture. /// Compute best palette for given picture.
/// @param size in pixels
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)
{ {

View File

@ -153,8 +153,8 @@ long Perceptual_lightness(T_Components *color);
void OT_init(T_Occurrence_table * t); void OT_init(T_Occurrence_table * t);
T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b); T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b);
void OT_delete(T_Occurrence_table * t); void OT_delete(T_Occurrence_table * t);
int OT_get(T_Occurrence_table * t,int r,int g,int b); int OT_get(T_Occurrence_table * t,byte r,byte g,byte b);
void OT_inc(T_Occurrence_table * t,int r,int g,int b); void OT_inc(T_Occurrence_table * t,byte r,byte g,byte b);
void OT_count_occurrences(T_Occurrence_table * t,T_Bitmap24B image,int size); void OT_count_occurrences(T_Occurrence_table * t,T_Bitmap24B image,int size);
@ -163,8 +163,8 @@ void OT_count_occurrences(T_Occurrence_table * t,T_Bitmap24B image,int size);
///////////////////////////////////////// Méthodes de gestion des clusters // ///////////////////////////////////////// Méthodes de gestion des clusters //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
void Cluster_pack(T_Cluster * c,T_Occurrence_table * to); void Cluster_pack(T_Cluster * c,const T_Occurrence_table * const to);
void Cluster_split(T_Cluster * c,T_Cluster * c1,T_Cluster * c2,int hue,T_Occurrence_table * to); void Cluster_split(T_Cluster * c,T_Cluster * c1,T_Cluster * c2,int hue,const T_Occurrence_table * const to);
void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to); void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to);
@ -178,7 +178,7 @@ T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to);
void CS_Delete(T_Cluster_set * cs); void CS_Delete(T_Cluster_set * cs);
void CS_Get(T_Cluster_set * cs,T_Cluster ** c); 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,T_Occurrence_table * 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);