diff --git a/src/colorred.c b/src/colorred.c index 4eaacc44..bdebd672 100644 --- a/src/colorred.c +++ b/src/colorred.c @@ -34,23 +34,24 @@ but : * No loss of precision */ -CT_Node* CT_new() {return NULL;} +CT_Tree* CT_new() {return calloc(1, sizeof(CT_Tree));} // debug helper +/* void CT_Print(CT_Node* node) { printf("R %d %d\tG %d %d\tB %d %d\ti %d\n", node->Rmin, node->Rmax, node->Gmin, node->Gmax, node->Bmin, node->Bmax, node->index); } +*/ -void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin, +void CT_set(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin, byte Rmax, byte Gmax, byte Bmax, byte index) { - int i; CT_Node* parent; // Create and setup node - CT_Node* node = malloc(sizeof(CT_Node)); + CT_Node* node = &colorTree->nodes[++colorTree->nodecount]; node->Rmin = Rmin; node->Gmin = Gmin; @@ -58,20 +59,11 @@ void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin, node->Rmax = Rmax; node->Gmax = Gmax; node->Bmax = Bmax; - node->index = index; - - printf("Add node:"); - CT_Print(node); - - for(i = 0; i < 2; i++) - node->children[i] = NULL; + node->children[1] = index; // Now insert it in tree - parent = *colorTree; - if (parent == NULL) { - // This is our first node. - *colorTree = node; - } else for(;;) { + parent = &colorTree->nodes[0]; + if (parent != NULL) for(;;) { // Find where to insert ourselves // pre-condition: the parent we're looking at is a superset of the node we're inserting @@ -81,12 +73,12 @@ void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin, // 1 child: either we're included in the child, and recurse, or we''re not, and insert at child 1 // 2 child: one of them has to be a superset of the node. - if (parent->children[0] == NULL) + if (parent->children[0] == 0) { - parent->children[0] = node; + parent->children[0] = colorTree->nodecount; break; } else { - CT_Node* child0 = parent->children[0]; + CT_Node* child0 = &colorTree->nodes[parent->children[0]]; if (child0->Rmin <= node->Rmin && child0->Gmin <= node->Gmin && child0->Bmin <= node->Bmin @@ -95,28 +87,31 @@ void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin, && child0->Bmax >= node->Bmax ) { parent = child0; - } else if(parent->children[1] == NULL) + } else if(parent->children[1] == 0) { - parent->children[1] = node; + parent->children[1] = colorTree->nodecount; break; } else { - parent = parent->children[1]; + parent = &colorTree->nodes[parent->children[1]]; } } } } -byte CT_get(CT_Node* node, byte r, byte g, byte b) +byte CT_get(CT_Tree* tree, byte r, byte g, byte b) { // pre condition: node contains (rgb) // find the leaf that also contains (rgb) + CT_Node* node = &tree->nodes[0]; + for(;;) { - if(node->children[0] == NULL) - return node->index; + if(node->children[0] == 0) + // return the palette index + return node->children[1]; else { // Left or right ? - CT_Node* child0 = node->children[0]; + CT_Node* child0 = &tree->nodes[node->children[0]]; if (child0->Rmin <= r && child0->Gmin <= g && child0->Bmin <= b @@ -128,20 +123,13 @@ byte CT_get(CT_Node* node, byte r, byte g, byte b) node = child0; } else { // right - node = node->children[1]; + node = &tree->nodes[node->children[1]]; } } } } -void CT_delete(CT_Node* tree) +void CT_delete(CT_Tree* tree) { - int i; - if (tree == NULL) - return; - for (i = 0; i < 2; i++) - { - CT_delete(tree->children[i]); - } free(tree); } diff --git a/src/colorred.h b/src/colorred.h index 62d1ea12..b1927c1f 100644 --- a/src/colorred.h +++ b/src/colorred.h @@ -55,17 +55,22 @@ typedef struct CT_Node_s // * makes them smaller // * helps with cache locality - // palette index (valid iff any child is NULL) - byte index; - - // child nodes - struct CT_Node_s* children[2]; + // Child nodes : + // Either two indices in the colorTree array, or + // 0 and a palette index + // 0 is not a valid array index, because no node points to the root ! + word children[2]; } CT_Node; -CT_Node* CT_new(); -void CT_delete(CT_Node* t); -byte CT_get(CT_Node* t,byte r,byte g,byte b); -void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin, +typedef struct ColorTree_S { + short nodecount; + CT_Node nodes[511]; +} CT_Tree; + +CT_Tree* CT_new(); +void CT_delete(CT_Tree* t); +byte CT_get(CT_Tree* t,byte r,byte g,byte b); +void CT_set(CT_Tree* colorTree, byte Rmin, byte Gmin, byte Bmin, byte Rmax, byte Gmax, byte Bmax, byte index); #endif diff --git a/src/op_c.c b/src/op_c.c index 7f6ce582..f8744f51 100644 --- a/src/op_c.c +++ b/src/op_c.c @@ -435,11 +435,9 @@ ENDCRUSH: c->bmin=bmin; c->bmax=bmax; // Find the longest axis to know which way to split the cluster - // This multiplications are supposed to improve the result, but may or may not - // work, actually. - r=(c->rmax-c->rmin)*299; - g=(c->vmax-c->vmin)*587; - b=(c->bmax-c->bmin)*114; + r=(c->rmax-c->rmin); + g=(c->vmax-c->vmin); + b=(c->bmax-c->bmin); if (g>=r) { @@ -796,7 +794,7 @@ 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 // 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 -void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to, CT_Node** colorTree) +void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to, CT_Tree* colorTree) { T_Cluster current; T_Cluster Nouveau1; @@ -911,7 +909,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_Node** tc,T_Components * palette) +void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Components * palette) { int index; T_Cluster* current = cs->clusters; @@ -1034,11 +1032,11 @@ void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs) /// Compute best palette for given picture. -CT_Node* 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_Occurrence_table * to; - CT_Node* tc; + CT_Tree* tc; T_Cluster_set * cs; T_Gradient_set * ds; @@ -1050,13 +1048,13 @@ CT_Node* Optimize_palette(T_Bitmap24B image, int size, return 0; tc = CT_new(); - /* + if (tc == NULL) { OT_delete(to); return NULL; } -*/ + // Count pixels for each color OT_count_occurrences(to, image, size); @@ -1071,7 +1069,7 @@ CT_Node* Optimize_palette(T_Bitmap24B image, int size, // Ok, everything was allocated // Generate the cluster set with median cut algorithm - CS_Generate(cs, to, &tc); + CS_Generate(cs, to, tc); //CS_Check(cs); // Compute the color data for each cluster (palette entry + HL) @@ -1091,7 +1089,7 @@ CT_Node* 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); //CS_Check(cs); CS_Delete(cs); @@ -1119,7 +1117,7 @@ int Modified_value(int value,int modif) /// Convert a 24b image to 256 colors (with a given palette and conversion table) /// This destroys the 24b picture ! /// Uses floyd steinberg dithering. -void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette,CT_Node* tc) +void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette,CT_Tree* tc) { T_Bitmap24B current; T_Bitmap24B c_plus1; @@ -1215,7 +1213,7 @@ void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B sour /// Converts from 24b to 256c without dithering, using given conversion table void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest, T_Bitmap24B source, int width, int height, __attribute__((unused)) T_Components * palette, - CT_Node* tc) + CT_Tree* tc) { T_Bitmap24B current; T_Bitmap256 d; @@ -1274,7 +1272,7 @@ int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int return Convert_24b_bitmap_to_256_fast(dest, source, width, height, palette); #else - CT_Node* table; // table de conversion + CT_Tree* table; // table de conversion int ip; // index de précision pour la conversion // On essaye d'obtenir une table de conversion qui loge en mémoire, avec la diff --git a/src/op_c.h b/src/op_c.h index 161e77c5..de7d4d6b 100644 --- a/src/op_c.h +++ b/src/op_c.h @@ -158,9 +158,9 @@ T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to); void CS_Delete(T_Cluster_set * cs); 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,T_Occurrence_table * to, CT_Node** colorTree); +void CS_Generate(T_Cluster_set * cs,T_Occurrence_table * 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_Node** tc,T_Components * palette); +void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Tree* tc,T_Components * palette); ///////////////////////////////////////////////////////////////////////////// //////////////////////////// Méthodes de gestion des ensembles de dégradés //