The cluster system for color reduction when loading a truecolor image now uses a linked list instead of a table. This fix a potential problem because there was an overlapping memcpy. It also avoids copying the big cluster table around and just moves pointer around. It should be faster but I did not really noticed any change on my computer :(. Maybe it's too fast...
The same can probably be done for the gradient sets. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@927 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
		
							parent
							
								
									3a7edb8323
								
							
						
					
					
						commit
						e877292ca2
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@ -210,7 +210,7 @@ else
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # Compiles a regular linux exectutable for the native platform
 | 
					        # Compiles a regular linux exectutable for the native platform
 | 
				
			||||||
        BIN = grafx2
 | 
					        BIN = grafx2
 | 
				
			||||||
        COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT)
 | 
					        COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT)
 | 
				
			||||||
        LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng
 | 
					        LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng
 | 
				
			||||||
		# Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
 | 
							# Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
 | 
				
			||||||
		CC = gcc
 | 
							CC = gcc
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										327
									
								
								op_c.c
									
									
									
									
									
								
							
							
						
						
									
										327
									
								
								op_c.c
									
									
									
									
									
								
							@ -657,37 +657,40 @@ void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to)
 | 
				
			|||||||
//////////////////////////// M‚thodes de gestion des ensembles de clusters //
 | 
					//////////////////////////// M‚thodes de gestion des ensembles de clusters //
 | 
				
			||||||
/////////////////////////////////////////////////////////////////////////////
 | 
					/////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Setup the first cluster before we start the operations
 | 
				
			||||||
void CS_Init(T_Cluster_set * cs,T_Occurrence_table * to)
 | 
					void CS_Init(T_Cluster_set * cs,T_Occurrence_table * to)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  cs->clusters[0].Rmin=cs->clusters[0].rmin=0;
 | 
					  cs->clusters->Rmin = cs->clusters->rmin = 0;
 | 
				
			||||||
  cs->clusters[0].Gmin=cs->clusters[0].vmin=0;
 | 
					  cs->clusters->Gmin = cs->clusters->vmin = 0;
 | 
				
			||||||
  cs->clusters[0].Bmin=cs->clusters[0].bmin=0;
 | 
					  cs->clusters->Bmin = cs->clusters->bmin = 0;
 | 
				
			||||||
  cs->clusters[0].Rmax=cs->clusters[0].rmax=to->rng_r-1;
 | 
					  cs->clusters->Rmax = cs->clusters->rmax = to->rng_r-1;
 | 
				
			||||||
  cs->clusters[0].Vmax=cs->clusters[0].vmax=to->rng_g-1;
 | 
					  cs->clusters->Vmax = cs->clusters->vmax = to->rng_g-1;
 | 
				
			||||||
  cs->clusters[0].Bmax=cs->clusters[0].bmax=to->rng_b-1;
 | 
					  cs->clusters->Bmax = cs->clusters->bmax = to->rng_b-1;
 | 
				
			||||||
  Cluster_analyser(cs->clusters+0,to);
 | 
					  cs->clusters->next = NULL;
 | 
				
			||||||
  // Et hop : le 1er ensemble de couleurs est initialis‚
 | 
					  Cluster_analyser(cs->clusters,to);
 | 
				
			||||||
  cs->nb=1;
 | 
					  cs->nb=1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Allocate a new cluster set
 | 
				
			||||||
T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to)
 | 
					T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  T_Cluster_set * n;
 | 
					  T_Cluster_set * n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  n=(T_Cluster_set *)malloc(sizeof(T_Cluster_set));
 | 
					  n=(T_Cluster_set *)malloc(sizeof(T_Cluster_set));
 | 
				
			||||||
  if (n!=0)
 | 
					  if (n != NULL)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    // On recopie les paramŠtres demand‚s
 | 
					    // On recopie les paramŠtres demand‚s
 | 
				
			||||||
    n->nb_max=OT_count_colors(to);
 | 
					    n->nb_max=OT_count_colors(to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // On vient de compter le nombre de couleurs existantes, s'il est plus grand que 256 on limit à 256 (nombre de couleurs voulu au final)
 | 
					    // On vient de compter le nombre de couleurs existantes, s'il est plus grand que 256 on limite à 256 
 | 
				
			||||||
 | 
						// (nombre de couleurs voulu au final)
 | 
				
			||||||
    if (n->nb_max>nbmax)
 | 
					    if (n->nb_max>nbmax)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      n->nb_max=nbmax;
 | 
					      n->nb_max=nbmax;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // On tente d'allouer la table
 | 
					    // On tente d'allouer le premier cluster
 | 
				
			||||||
    n->clusters=(T_Cluster *)malloc(nbmax*sizeof(T_Cluster));
 | 
					    n->clusters=(T_Cluster *)malloc(sizeof(T_Cluster));
 | 
				
			||||||
    if (n->clusters!=NULL)
 | 
					    if (n->clusters!=NULL)
 | 
				
			||||||
      // C'est bon! On initialise
 | 
					      // C'est bon! On initialise
 | 
				
			||||||
      CS_Init(n,to);
 | 
					      CS_Init(n,to);
 | 
				
			||||||
@ -702,68 +705,74 @@ T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to)
 | 
				
			|||||||
  return n;
 | 
					  return n;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Free a cluster set
 | 
				
			||||||
void CS_Delete(T_Cluster_set * cs)
 | 
					void CS_Delete(T_Cluster_set * cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  free(cs->clusters);
 | 
						T_Cluster* nxt;
 | 
				
			||||||
  free(cs);
 | 
						while(cs->clusters != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nxt = cs->clusters->next;
 | 
				
			||||||
 | 
					  		free(cs->clusters);
 | 
				
			||||||
 | 
							cs->clusters = nxt;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  	free(cs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CS_Get(T_Cluster_set * cs,T_Cluster * c)
 | 
					void CS_Get(T_Cluster_set * cs,T_Cluster * c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int index;
 | 
					  T_Cluster* current = cs->clusters;
 | 
				
			||||||
 | 
					  T_Cluster* prev = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // On cherche un cluster que l'on peut couper en deux, donc avec au moins deux valeurs
 | 
					  // Search a cluster with at least 2 distinct colors so we can split it
 | 
				
			||||||
  // différentes sur l'une des composantes
 | 
					  do
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
					  {
 | 
				
			||||||
    if ( (cs->clusters[index].rmin<cs->clusters[index].rmax) ||
 | 
					    if ( (current->rmin < current->rmax) ||
 | 
				
			||||||
         (cs->clusters[index].vmin<cs->clusters[index].vmax) ||
 | 
					         (current->vmin < current->vmax) ||
 | 
				
			||||||
         (cs->clusters[index].bmin<cs->clusters[index].bmax) )
 | 
					         (current->bmin < current->bmax) )
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // On le recopie dans c
 | 
						prev = current;
 | 
				
			||||||
  *c=cs->clusters[index];
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
  // On décrémente le nombre et on décale tous les clusters suivants
 | 
					  } while((current = current -> next));
 | 
				
			||||||
  // Sachant qu'on va réinsérer juste après, il me semble que ça serait une bonne idée de gérer les clusters 
 | 
					
 | 
				
			||||||
  // comme une liste chainée... on n'a aucun accès direct dedans, que des parcours ...
 | 
					  // copy it to c
 | 
				
			||||||
 | 
					  *c = *current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // remove it from the list
 | 
				
			||||||
  cs->nb--;
 | 
					  cs->nb--;
 | 
				
			||||||
  memcpy((cs->clusters+index),(cs->clusters+index+1),(cs->nb-index)*sizeof(T_Cluster));
 | 
					
 | 
				
			||||||
 | 
					  if(prev)
 | 
				
			||||||
 | 
						prev->next = current->next;
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
						cs->clusters = current->next;
 | 
				
			||||||
 | 
					  free(current);
 | 
				
			||||||
 | 
					  current = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CS_Set(T_Cluster_set * cs,T_Cluster * c)
 | 
					void CS_Set(T_Cluster_set * cs,T_Cluster * c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int index;
 | 
					  T_Cluster* current = cs->clusters;
 | 
				
			||||||
  // int decalage;
 | 
					  T_Cluster* prev = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Le tableau des clusters est trié par nombre d'occurences. Donc on cherche la position du premier cluster 
 | 
					  // Search the first cluster that is smaller than ours
 | 
				
			||||||
  // qui est plus grand que le notre
 | 
					  if(current != NULL) // don't search if the list is empty
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
					  do
 | 
				
			||||||
    if (cs->clusters[index].occurences<c->occurences)
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
    if (((OPTPAL_Cluster[index].rmax-OPTPAL_Cluster[index].rmin+1)*
 | 
					 | 
				
			||||||
         (OPTPAL_Cluster[index].gmax-OPTPAL_Cluster[index].gmin+1)*
 | 
					 | 
				
			||||||
         (OPTPAL_Cluster[index].bmax-OPTPAL_Cluster[index].bmin+1))
 | 
					 | 
				
			||||||
        <
 | 
					 | 
				
			||||||
        ((Set->rmax-Set->rmin+1)*
 | 
					 | 
				
			||||||
         (Set->gmax-Set->gmin+1)*
 | 
					 | 
				
			||||||
         (Set->bmax-Set->bmin+1))
 | 
					 | 
				
			||||||
       )
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (index<cs->nb)
 | 
					 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    // On distingue ici une insertion plutot qu'un placement en fin de liste.
 | 
					    if (current->occurences < c->occurences)
 | 
				
			||||||
    // On doit donc décaler les ensembles suivants vers la fin pour se faire
 | 
							break;
 | 
				
			||||||
    // une place dans la liste.
 | 
						prev = current;
 | 
				
			||||||
 | 
					  } while((current = current -> next));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //for (decalage=cs->nb;decalage>index;decalage--)
 | 
					  // Now insert our cluster just before the one we found
 | 
				
			||||||
    //  memcpy((cs->clusters+decalage),(cs->clusters+decalage-1),sizeof(T_Cluster));
 | 
					  c -> next = current;
 | 
				
			||||||
    memmove(cs->clusters+index+1,cs->clusters+index,(cs->nb-index)*sizeof(T_Cluster));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cs->clusters[index]=*c;
 | 
					  current = malloc(sizeof(T_Cluster));
 | 
				
			||||||
  cs->nb++;
 | 
					  *current = *c ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(prev) prev -> next = current;
 | 
				
			||||||
 | 
					  else cs->clusters = current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cs -> nb++;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Détermination de la meilleure palette en utilisant l'algo Median Cut :
 | 
					// Détermination de la meilleure palette en utilisant l'algo Median Cut :
 | 
				
			||||||
@ -802,96 +811,91 @@ void CS_Generate(T_Cluster_set * cs,T_Occurrence_table * to)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to)
 | 
					void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int index;
 | 
					 | 
				
			||||||
  T_Cluster * c;
 | 
					  T_Cluster * c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (index=0,c=cs->clusters;index<cs->nb;index++,c++)
 | 
					  for (c=cs->clusters;c!=NULL;c=c->next)
 | 
				
			||||||
    Cluster_compute_hue(c,to);
 | 
					    Cluster_compute_hue(c,to);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CS_Sort_by_chrominance(T_Cluster_set * cs)
 | 
					void CS_Sort_by_chrominance(T_Cluster_set * cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int byte_used[256];
 | 
						T_Cluster* nc;
 | 
				
			||||||
  int decalages[256];
 | 
						T_Cluster* prev = NULL;
 | 
				
			||||||
  int index;
 | 
						T_Cluster* place;
 | 
				
			||||||
  T_Cluster * nc;
 | 
						T_Cluster* newlist = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  nc=(T_Cluster *)malloc(cs->nb_max*sizeof(T_Cluster));
 | 
						while((nc = cs->clusters))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// Remove the first cluster from the original list
 | 
				
			||||||
 | 
							nc = cs->clusters;
 | 
				
			||||||
 | 
							cs->clusters = cs->clusters->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialisation de la table d'occurence de chaque octet
 | 
							// Find his position in the new list
 | 
				
			||||||
  for (index=0;index<256;index++)
 | 
							for(place = newlist;place != NULL; place = place->next)
 | 
				
			||||||
    byte_used[index]=0;
 | 
							{
 | 
				
			||||||
 | 
								if(place->h > nc->h) break;
 | 
				
			||||||
 | 
								prev = place;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Comptage du nombre d'occurences de chaque octet
 | 
							// Chain it there
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
							nc->next = place;
 | 
				
			||||||
    byte_used[cs->clusters[index].h]++;
 | 
							if(prev) prev->next = nc;
 | 
				
			||||||
 | 
							else newlist = nc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Calcul de la table des d‚calages
 | 
						}
 | 
				
			||||||
  decalages[0]=0;
 | 
					 | 
				
			||||||
  for (index=1;index<256;index++)
 | 
					 | 
				
			||||||
    decalages[index]=decalages[index-1]+byte_used[index-1];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Copie r‚ordonn‚e dans la nouvelle liste
 | 
						// Put the new list bavk in place
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
						cs->clusters = newlist;
 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    nc[decalages[cs->clusters[index].h]]=cs->clusters[index];
 | 
					 | 
				
			||||||
    decalages[cs->clusters[index].h]++;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Remplacement de la liste d‚sordonn‚e par celle tri‚e
 | 
					 | 
				
			||||||
  free(cs->clusters);
 | 
					 | 
				
			||||||
  cs->clusters=nc;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CS_Sort_by_luminance(T_Cluster_set * cs)
 | 
					void CS_Sort_by_luminance(T_Cluster_set * cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int byte_used[256];
 | 
						T_Cluster* nc;
 | 
				
			||||||
  int decalages[256];
 | 
						T_Cluster* prev = NULL;
 | 
				
			||||||
  int index;
 | 
						T_Cluster* place;
 | 
				
			||||||
  T_Cluster * nc;
 | 
						T_Cluster* newlist = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  nc=(T_Cluster *)malloc(cs->nb_max*sizeof(T_Cluster));
 | 
						while((nc = cs->clusters))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// Remove the first cluster from the original list
 | 
				
			||||||
 | 
							nc = cs->clusters;
 | 
				
			||||||
 | 
							cs->clusters = cs->clusters->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialisation de la table d'occurence de chaque octet
 | 
							// Find his position in the new list
 | 
				
			||||||
  for (index=0;index<256;index++)
 | 
							for(place = newlist;place != NULL; place = place->next)
 | 
				
			||||||
    byte_used[index]=0;
 | 
							{
 | 
				
			||||||
 | 
								if(place->l > nc->l) break;
 | 
				
			||||||
 | 
								prev = place;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Comptage du nombre d'occurences de chaque octet
 | 
							// Chain it there
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
							nc->next = place;
 | 
				
			||||||
    byte_used[cs->clusters[index].l]++;
 | 
							if(prev) prev->next = nc;
 | 
				
			||||||
 | 
							else newlist = nc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Calcul de la table des d‚calages
 | 
						}
 | 
				
			||||||
  decalages[0]=0;
 | 
					 | 
				
			||||||
  for (index=1;index<256;index++)
 | 
					 | 
				
			||||||
    decalages[index]=decalages[index-1]+byte_used[index-1];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Copie r‚ordonn‚e dans la nouvelle liste
 | 
						// Put the new list bavk in place
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
						cs->clusters = newlist;
 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    nc[decalages[cs->clusters[index].l]]=cs->clusters[index];
 | 
					 | 
				
			||||||
    decalages[cs->clusters[index].l]++;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Remplacement de la liste d‚sordonn‚e par celle tri‚e
 | 
					 | 
				
			||||||
  free(cs->clusters);
 | 
					 | 
				
			||||||
  cs->clusters=nc;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette)
 | 
					void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int index;
 | 
					  int index;
 | 
				
			||||||
  int r,g,b;
 | 
					  int r,g,b;
 | 
				
			||||||
 | 
					  T_Cluster* current = cs->clusters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (index=0;index<cs->nb;index++)
 | 
					  for (index=0;index<cs->nb;index++)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    palette[index].R=cs->clusters[index].r;
 | 
					    palette[index].R=current->r;
 | 
				
			||||||
    palette[index].G=cs->clusters[index].g;
 | 
					    palette[index].G=current->g;
 | 
				
			||||||
    palette[index].B=cs->clusters[index].b;
 | 
					    palette[index].B=current->b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (r=cs->clusters[index].Rmin;r<=cs->clusters[index].Rmax;r++)
 | 
					    for (r=current->Rmin; r<=current->Rmax; r++)
 | 
				
			||||||
      for (g=cs->clusters[index].Gmin;g<=cs->clusters[index].Vmax;g++)
 | 
					      for (g=current->Gmin;g<=current->Vmax;g++)
 | 
				
			||||||
        for (b=cs->clusters[index].Bmin;b<=cs->clusters[index].Bmax;b++)
 | 
					        for (b=current->Bmin;b<=current->Bmax;b++)
 | 
				
			||||||
          CT_set(tc,r,g,b,index);
 | 
					          CT_set(tc,r,g,b,index);
 | 
				
			||||||
 | 
						current = current->next;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -902,9 +906,9 @@ void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table *
 | 
				
			|||||||
void GS_Init(T_Gradient_set * ds,T_Cluster_set * cs)
 | 
					void GS_Init(T_Gradient_set * ds,T_Cluster_set * cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ds->gradients[0].nb_colors=1;
 | 
					    ds->gradients[0].nb_colors=1;
 | 
				
			||||||
    ds->gradients[0].min=cs->clusters[0].h;
 | 
					    ds->gradients[0].min=cs->clusters->h;
 | 
				
			||||||
    ds->gradients[0].max=cs->clusters[0].h;
 | 
					    ds->gradients[0].max=cs->clusters->h;
 | 
				
			||||||
    ds->gradients[0].hue=cs->clusters[0].h;
 | 
					    ds->gradients[0].hue=cs->clusters->h;
 | 
				
			||||||
    // Et hop : le 1er ensemble de d‚grad‚s est initialis‚
 | 
					    // Et hop : le 1er ensemble de d‚grad‚s est initialis‚
 | 
				
			||||||
    ds->nb=1;
 | 
					    ds->nb=1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -943,57 +947,60 @@ void GS_Delete(T_Gradient_set * ds)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs)
 | 
					void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ic,id; // Les indexs de parcours des ensembles
 | 
					    int id; // Les indexs de parcours des ensembles
 | 
				
			||||||
    int best_gradient; // Meilleur d‚grad‚
 | 
					    int best_gradient; // Meilleur d‚grad‚
 | 
				
			||||||
    int best_diff; // Meilleure diff‚rence de chrominance
 | 
					    int best_diff; // Meilleure diff‚rence de chrominance
 | 
				
			||||||
    int diff;  // difference de chrominance courante
 | 
					    int diff;  // difference de chrominance courante
 | 
				
			||||||
 | 
						T_Cluster * current = cs->clusters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Pour chacun des clusters … traiter
 | 
					    // Pour chacun des clusters … traiter
 | 
				
			||||||
    for (ic=0;ic<cs->nb;ic++)
 | 
					    do
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        // On recherche le d‚grad‚ le plus proche de la chrominance du cluster
 | 
							// On recherche le d‚grad‚ le plus proche de la chrominance du cluster
 | 
				
			||||||
        best_gradient=-1;
 | 
							best_gradient=-1;
 | 
				
			||||||
        best_diff=99999999;
 | 
							best_diff=99999999;
 | 
				
			||||||
        for (id=0;id<ds->nb;id++)
 | 
							for (id=0;id<ds->nb;id++)
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            diff=abs(cs->clusters[ic].h - ds->gradients[id].hue);
 | 
								diff=abs(current->h - ds->gradients[id].hue);
 | 
				
			||||||
            if ((best_diff>diff) && (diff<16))
 | 
								if ((best_diff>diff) && (diff<16))
 | 
				
			||||||
            {
 | 
								{
 | 
				
			||||||
                best_gradient=id;
 | 
									best_gradient=id;
 | 
				
			||||||
                best_diff=diff;
 | 
									best_diff=diff;
 | 
				
			||||||
            }
 | 
								}
 | 
				
			||||||
        }
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Si on a trouv‚ un d‚grad‚ dans lequel inclure le cluster
 | 
							// Si on a trouv‚ un d‚grad‚ dans lequel inclure le cluster
 | 
				
			||||||
        if (best_gradient!=-1)
 | 
							if (best_gradient!=-1)
 | 
				
			||||||
    {
 | 
							{
 | 
				
			||||||
      // On met … jour le d‚grad‚
 | 
								// On met … jour le d‚grad‚
 | 
				
			||||||
      if (cs->clusters[ic].h < ds->gradients[best_gradient].min)
 | 
								if (current->h < ds->gradients[best_gradient].min)
 | 
				
			||||||
        ds->gradients[best_gradient].min=cs->clusters[ic].h;
 | 
									ds->gradients[best_gradient].min=current->h;
 | 
				
			||||||
      if (cs->clusters[ic].h > ds->gradients[best_gradient].max)
 | 
								if (current->h > ds->gradients[best_gradient].max)
 | 
				
			||||||
        ds->gradients[best_gradient].max=cs->clusters[ic].h;
 | 
									ds->gradients[best_gradient].max=current->h;
 | 
				
			||||||
      ds->gradients[best_gradient].hue=((ds->gradients[best_gradient].hue*
 | 
								ds->gradients[best_gradient].hue=((ds->gradients[best_gradient].hue*
 | 
				
			||||||
                                ds->gradients[best_gradient].nb_colors)
 | 
											ds->gradients[best_gradient].nb_colors)
 | 
				
			||||||
                               +cs->clusters[ic].h)
 | 
										+current->h)
 | 
				
			||||||
                              /(ds->gradients[best_gradient].nb_colors+1);
 | 
									/(ds->gradients[best_gradient].nb_colors+1);
 | 
				
			||||||
      ds->gradients[best_gradient].nb_colors++;
 | 
								ds->gradients[best_gradient].nb_colors++;
 | 
				
			||||||
    }
 | 
							}
 | 
				
			||||||
    else
 | 
							else
 | 
				
			||||||
    {
 | 
							{
 | 
				
			||||||
      // On cr‚e un nouveau d‚grad‚
 | 
								// On cr‚e un nouveau d‚grad‚
 | 
				
			||||||
      best_gradient=ds->nb;
 | 
								best_gradient=ds->nb;
 | 
				
			||||||
      ds->gradients[best_gradient].nb_colors=1;
 | 
								ds->gradients[best_gradient].nb_colors=1;
 | 
				
			||||||
      ds->gradients[best_gradient].min=cs->clusters[ic].h;
 | 
								ds->gradients[best_gradient].min=current->h;
 | 
				
			||||||
      ds->gradients[best_gradient].max=cs->clusters[ic].h;
 | 
								ds->gradients[best_gradient].max=current->h;
 | 
				
			||||||
      ds->gradients[best_gradient].hue=cs->clusters[ic].h;
 | 
								ds->gradients[best_gradient].hue=current->h;
 | 
				
			||||||
      ds->nb++;
 | 
								ds->nb++;
 | 
				
			||||||
    }
 | 
							}
 | 
				
			||||||
    cs->clusters[ic].h=best_gradient;
 | 
							current->h=best_gradient;
 | 
				
			||||||
  }
 | 
						} while((current = current->next));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // On redistribue les valeurs dans les clusters
 | 
						// On redistribue les valeurs dans les clusters
 | 
				
			||||||
  for (ic=0;ic<cs->nb;ic++)
 | 
						current = cs -> clusters;
 | 
				
			||||||
    cs->clusters[ic].h=ds->gradients[cs->clusters[ic].h].hue;
 | 
						do
 | 
				
			||||||
 | 
							current->h=ds->gradients[current->h].hue;
 | 
				
			||||||
 | 
						while((current = current ->next));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								op_c.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								op_c.h
									
									
									
									
									
								
							@ -88,7 +88,7 @@ typedef struct
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
///////////////////////////////////////// Définition d'un ensemble de couleur
 | 
					///////////////////////////////////////// Définition d'un ensemble de couleur
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct S_Cluster
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int occurences; // Nb total d'occurences des couleurs de l'ensemble
 | 
					  int occurences; // Nb total d'occurences des couleurs de l'ensemble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -106,6 +106,8 @@ typedef struct
 | 
				
			|||||||
  byte r,g,b;      // color synthétisant l'ensemble
 | 
					  byte r,g,b;      // color synthétisant l'ensemble
 | 
				
			||||||
  byte h;          // Chrominance
 | 
					  byte h;          // Chrominance
 | 
				
			||||||
  byte l;          // Luminosité
 | 
					  byte l;          // Luminosité
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  struct S_Cluster* next;
 | 
				
			||||||
} T_Cluster;
 | 
					} T_Cluster;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										9
									
								
								setup.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								setup.c
									
									
									
									
									
								
							@ -57,7 +57,8 @@ int Create_ConfigDirectory(char * config_dir)
 | 
				
			|||||||
// Determine which directory contains the executable.
 | 
					// Determine which directory contains the executable.
 | 
				
			||||||
// IN: Main's argv[0], some platforms need it, some don't.
 | 
					// IN: Main's argv[0], some platforms need it, some don't.
 | 
				
			||||||
// OUT: Write into program_dir. Trailing / or \ is kept.
 | 
					// OUT: Write into program_dir. Trailing / or \ is kept.
 | 
				
			||||||
// Note : in fact this is only used to check for the datafiles and fonts in this same directory.
 | 
					// Note : in fact this is only used to check for the datafiles and fonts in 
 | 
				
			||||||
 | 
					// this same directory.
 | 
				
			||||||
void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir)
 | 
					void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  #undef ARG_UNUSED
 | 
					  #undef ARG_UNUSED
 | 
				
			||||||
@ -76,9 +77,9 @@ void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Others: The part of argv[0] before the executable name.    
 | 
					  // Others: The part of argv[0] before the executable name.    
 | 
				
			||||||
  // Keep the last \ or /.
 | 
					  // Keep the last \ or /.
 | 
				
			||||||
  // Note that on Unix, once installed, the executable is called from a shell script
 | 
					  // Note that on Unix, once installed, the executable is called from a shell
 | 
				
			||||||
  // sitting in /usr/local/bin/, this allows argv[0] to contain the full path.
 | 
					  // script sitting in /usr/local/bin/, this allows argv[0] to contain the full
 | 
				
			||||||
  // On Windows, Mingw32 already provides the full path in all cases.
 | 
					  // path. On Windows, Mingw32 already provides the full path in all cases.
 | 
				
			||||||
  #else
 | 
					  #else
 | 
				
			||||||
    Extract_path(program_dir, argv0);
 | 
					    Extract_path(program_dir, argv0);
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user