Improved brush rotation by adding 3 steps of scale2x. Result is not as good as I hoped, but for large flat surfaces, the edges are indeed much smoother than before.

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1789 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2011-06-04 15:22:13 +00:00
parent 1da0c96db8
commit 2d8c061e32
6 changed files with 263 additions and 38 deletions

View File

@ -36,6 +36,10 @@
#include "sdlscreen.h" #include "sdlscreen.h"
#include "brush.h" #include "brush.h"
// Data used during brush rotation operation
static byte * Brush_rotate_buffer;
static int Brush_rotate_width;
static int Brush_rotate_height;
// Calcul de redimensionnement du pinceau pour éviter les débordements de // Calcul de redimensionnement du pinceau pour éviter les débordements de
// l'écran et de l'image // l'écran et de l'image
@ -1670,7 +1674,8 @@ void Interpolate_texture(int start_x,int start_y,int xt1,int yt1,
void Compute_quad_texture(int x1,int y1,int xt1,int yt1, void Compute_quad_texture( byte *texture, int texture_width,
int x1,int y1,int xt1,int yt1,
int x2,int y2,int xt2,int yt2, int x2,int y2,int xt2,int yt2,
int x3,int y3,int xt3,int yt3, int x3,int y3,int xt3,int yt3,
int x4,int y4,int xt4,int yt4, int x4,int y4,int xt4,int yt4,
@ -1719,7 +1724,7 @@ void Compute_quad_texture(int x1,int y1,int xt1,int yt1,
xt=Round((float)(ScanY_Xt[0][y])+(temp*(ScanY_Xt[1][y]-ScanY_Xt[0][y]))); xt=Round((float)(ScanY_Xt[0][y])+(temp*(ScanY_Xt[1][y]-ScanY_Xt[0][y])));
yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y]))); yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y])));
if (xt>=0 && yt>=0) if (xt>=0 && yt>=0)
buffer[x+(y*width)]=*(Brush_original_pixels + yt * Brush_width + xt); buffer[x+(y*width)]=*(texture + yt * texture_width + xt);
} }
for (; x<width; x++) for (; x<width; x++)
buffer[x+(y*width)]=Back_color; buffer[x+(y*width)]=Back_color;
@ -1735,14 +1740,87 @@ void Compute_quad_texture(int x1,int y1,int xt1,int yt1,
ScanY_Xt[0] = ScanY_Xt[1] = ScanY_Yt[0] = ScanY_Yt[1] = ScanY_X[0] = ScanY_X[1] = NULL; ScanY_Xt[0] = ScanY_Xt[1] = ScanY_Yt[0] = ScanY_Yt[1] = ScanY_X[0] = ScanY_X[1] = NULL;
} }
void Scale2x(byte **bitmap, int *width, int *height)
{
byte *new_bitmap;
int new_width;
int new_height;
int x_pos, y_pos;
byte b,d,e,f,h;
new_width=(*width)*2;
new_height=(*height)*2;
new_bitmap=(byte *)(malloc(new_width*new_height));
if (!new_bitmap)
return;
// Algorithm from scale2x sourceforge project
for (y_pos=0; y_pos<*height; y_pos++)
{
for (x_pos=0; x_pos<*width; x_pos++)
{
// Check colors in pixels: (E is center)
// A B C
// D E F
// G H I
e=*(*bitmap + y_pos* *width + x_pos);
d = (x_pos==0) ? e : *(*bitmap + y_pos* *width + x_pos-1);
f = (x_pos==*width-1) ? e : *(*bitmap + y_pos* *width + x_pos+1);
b = (y_pos==0) ? e : *(*bitmap + (y_pos-1)* *width + x_pos);
h = (y_pos==*height-1) ? e : *(*bitmap + (y_pos+1)* *width + x_pos);
if (b != h && d != f)
{
*(new_bitmap + (y_pos*2)*new_width + x_pos*2) = d == b ? d : e;
*(new_bitmap + (y_pos*2)*new_width + x_pos*2+1) = b == f ? f : e;
*(new_bitmap + (y_pos*2+1)*new_width + x_pos*2) = d == h ? d : e;
*(new_bitmap + (y_pos*2+1)*new_width + x_pos*2+1) = h == f ? f : e;
}
else
{
*(new_bitmap + (y_pos*2)*new_width + x_pos*2) = e;
*(new_bitmap + (y_pos*2)*new_width + x_pos*2+1) = e;
*(new_bitmap + (y_pos*2+1)*new_width + x_pos*2) = e;
*(new_bitmap + (y_pos*2+1)*new_width + x_pos*2+1) = e;
}
}
}
*width=new_width;
*height=new_height;
*bitmap=new_bitmap;
}
void Begin_brush_rotation(void)
{
Brush_rotate_buffer=Brush_original_pixels;
Brush_rotate_width=Brush_width;
Brush_rotate_height=Brush_height;
Scale2x(&Brush_rotate_buffer, &Brush_rotate_width, &Brush_rotate_height);
Scale2x(&Brush_rotate_buffer, &Brush_rotate_width, &Brush_rotate_height);
Scale2x(&Brush_rotate_buffer, &Brush_rotate_width, &Brush_rotate_height);
}
void End_brush_rotation(void)
{
if (Brush_rotate_buffer && Brush_rotate_buffer != Brush_original_pixels)
{
free(Brush_rotate_buffer);
Brush_rotate_buffer=NULL;
}
}
void Rotate_brush(float angle) void Rotate_brush(float angle)
{ {
byte * new_brush; byte * new_brush;
int new_brush_width; // Width de la nouvelle brosse int new_brush_width; // Width de la nouvelle brosse
int new_brush_height; // Height de la nouvelle brosse int new_brush_height; // Height de la nouvelle brosse
int offset=0;
short x1,y1,x2,y2,x3,y3,x4,y4; short x1,y1,x2,y2,x3,y3,x4,y4;
int start_x,end_x,start_y,end_y; int start_x,end_x,start_y,end_y;
int x_min,x_max,y_min,y_max; int x_min,x_max,y_min,y_max;
@ -1757,6 +1835,7 @@ void Rotate_brush(float angle)
start_y=1-(Brush_height>>1); start_y=1-(Brush_height>>1);
end_x=start_x+Brush_width-1; end_x=start_x+Brush_width-1;
end_y=start_y+Brush_height-1; end_y=start_y+Brush_height-1;
//offset = Brush_rotate_width/Brush_width-1;
Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1); Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1);
Transform_point(end_x ,start_y, cos_a,sin_a, &x2,&y2); Transform_point(end_x ,start_y, cos_a,sin_a, &x2,&y2);
@ -1780,10 +1859,11 @@ void Rotate_brush(float angle)
return; return;
} }
// Et maintenant on calcule la nouvelle brosse tournée. // Et maintenant on calcule la nouvelle brosse tournée.
Compute_quad_texture(x1,y1, 0, 0, Compute_quad_texture( Brush_rotate_buffer, Brush_rotate_width,
x2,y2,Brush_width-1, 0, x1,y1, offset, offset,
x3,y3, 0,Brush_height-1, x2,y2,Brush_rotate_width-offset-1, offset,
x4,y4,Brush_width-1,Brush_height-1, x3,y3, offset,Brush_rotate_height-offset-1,
x4,y4,Brush_rotate_width-offset-1,Brush_rotate_height-offset-1,
new_brush,new_brush_width,new_brush_height); new_brush,new_brush_width,new_brush_height);
if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL)) if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL))
@ -1802,7 +1882,8 @@ void Rotate_brush(float angle)
void Draw_quad_texture_preview(int x1,int y1,int xt1,int yt1, void Draw_quad_texture_preview(byte *texture, int texture_width,
int x1,int y1,int xt1,int yt1,
int x2,int y2,int xt2,int yt2, int x2,int y2,int xt2,int yt2,
int x3,int y3,int xt3,int yt3, int x3,int y3,int xt3,int yt3,
int x4,int y4,int xt4,int yt4) int x4,int y4,int xt4,int yt4)
@ -1861,7 +1942,7 @@ void Draw_quad_texture_preview(int x1,int y1,int xt1,int yt1,
yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y]))); yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y])));
if (xt>=0 && yt>=0) if (xt>=0 && yt>=0)
{ {
color=Read_pixel_from_brush(xt,yt); color=Brush_colormap[*(texture+xt+yt*texture_width)];
if (color!=Back_color) if (color!=Back_color)
Pixel_preview(x,y_,color); Pixel_preview(x,y_,color);
} }
@ -1885,6 +1966,7 @@ void Rotate_brush_preview(float angle)
int start_x,end_x,start_y,end_y; int start_x,end_x,start_y,end_y;
float cos_a=cos(angle); float cos_a=cos(angle);
float sin_a=sin(angle); float sin_a=sin(angle);
int offset=0;
// Calcul des coordonnées des 4 coins: // Calcul des coordonnées des 4 coins:
// 1 2 // 1 2
@ -1894,6 +1976,7 @@ void Rotate_brush_preview(float angle)
start_y=1-(Brush_height>>1); start_y=1-(Brush_height>>1);
end_x=start_x+Brush_width-1; end_x=start_x+Brush_width-1;
end_y=start_y+Brush_height-1; end_y=start_y+Brush_height-1;
//offset = Brush_rotate_width/Brush_width-1;
Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1); Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1);
Transform_point(end_x ,start_y, cos_a,sin_a, &x2,&y2); Transform_point(end_x ,start_y, cos_a,sin_a, &x2,&y2);
@ -1910,10 +1993,11 @@ void Rotate_brush_preview(float angle)
y4+=Brush_rotation_center_Y; y4+=Brush_rotation_center_Y;
// Et maintenant on dessine la brosse tournée. // Et maintenant on dessine la brosse tournée.
Draw_quad_texture_preview(x1,y1, 0, 0, Draw_quad_texture_preview(Brush_rotate_buffer, Brush_rotate_width,
x2,y2,Brush_width-1, 0, x1, y1, offset, offset,
x3,y3, 0,Brush_height-1, x2, y2, Brush_rotate_width-offset-1, offset,
x4,y4,Brush_width-1,Brush_height-1); x3, y3, offset, Brush_rotate_height-offset-1,
x4, y4, Brush_rotate_width-offset-1, Brush_rotate_height-offset-1);
start_x=Min(Min(x1,x2),Min(x3,x4)); start_x=Min(Min(x1,x2),Min(x3,x4));
end_x=Max(Max(x1,x2),Max(x3,x4)); end_x=Max(Max(x1,x2),Max(x3,x4));
start_y=Min(Min(y1,y2),Min(y3,y4)); start_y=Min(Min(y1,y2),Min(y3,y4));

View File

@ -125,5 +125,7 @@ byte Realloc_brush(word new_brush_width, word new_brush_height, byte *new_brush,
/// Sets brush's original palette and color mapping. /// Sets brush's original palette and color mapping.
void Brush_set_palette(T_Palette *palette); void Brush_set_palette(T_Palette *palette);
void Begin_brush_rotation(void);
void End_brush_rotation(void);
#endif #endif

View File

@ -42,7 +42,6 @@
#define M_PI 3.141592653589793238462643 #define M_PI 3.141592653589793238462643
#endif #endif
/// Simulates clicking the "Draw" button. /// Simulates clicking the "Draw" button.
void Return_to_draw_mode(void) void Return_to_draw_mode(void)
{ {
@ -971,8 +970,7 @@ void Rotate_brush_1_5(void)
{ {
dx=Paintbrush_X-Brush_rotation_center_X; dx=Paintbrush_X-Brush_rotation_center_X;
dy=Paintbrush_Y-Brush_rotation_center_Y; dy=Paintbrush_Y-Brush_rotation_center_Y;
angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); angle=M_2PI-atan2(dy,dx);
if (dy>0) angle=M_2PI-angle;
} }
if (Menu_is_visible) if (Menu_is_visible)

View File

@ -386,7 +386,7 @@ int OT_count_colors(T_Occurrence_table * t)
// Cluster management // Cluster management
// Clusters are boxes in the RGB spaces, defined by 6 corner coordinates : // Clusters are boxes in the RGB spaces, defined by 6 corner coordinates :
// Rmax, Rmin, Vmax (or Gmax), Vmin, Rmax, Rmin // Rmax, Rmin, vmax (or Vmax), vmin, Rmax, Rmin
// The median cut algorithm start with a single cluster covering the whole // The median cut algorithm start with a single cluster covering the whole
// colorspace then split it in two smaller clusters on the longest axis until // colorspace then split it in two smaller clusters on the longest axis until
// there are 256 non-empty clusters (with some tricks if the original image // there are 256 non-empty clusters (with some tricks if the original image
@ -403,6 +403,7 @@ void Cluster_pack(T_Cluster * c,T_Occurrence_table * to)
{ {
int rmin,rmax,vmin,vmax,bmin,bmax; int rmin,rmax,vmin,vmax,bmin,bmax;
int r,g,b; int r,g,b;
int nbocc;
// 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
@ -411,15 +412,15 @@ void Cluster_pack(T_Cluster * c,T_Occurrence_table * to)
// 256^3*sizeof(int) = 64MB table. If your computer has less free ram and // 256^3*sizeof(int) = 64MB table. If your computer has less free ram and
// malloc fails, this will not work at all ! // 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 <<16; rmax=c->rmin << 16;
vmin=c->vmax << 8; vmax=c->vmin << 8; vmin=c->vmax << 8; vmax=c->vmin << 8;
bmin=c->bmax; bmax=c->bmin; bmin=c->bmax; bmax=c->bmin;
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<<16;r<=c->rmax<<16;r+=1<<16)
for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
for (b=c->bmin;b<=c->bmax;b++) for (b=c->bmin;b<=c->bmax;b++)
@ -436,8 +437,8 @@ void Cluster_pack(T_Cluster * c,T_Occurrence_table * to)
c->occurences+=nbocc; c->occurences+=nbocc;
} }
} }
*/
/*
// Optimized version : find the extremums one at a time, so we can reduce the // Optimized version : find the extremums one at a time, so we can reduce the
// 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.
@ -460,10 +461,10 @@ RMAX:
if(to->table[r + g + b]) // OT_get if(to->table[r + g + b]) // OT_get
{ {
rmax=r; rmax=r;
goto VMIN; goto vmin;
} }
} }
VMIN: vmin:
for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
for(r=rmin;r<=rmax;r+=1<<16) for(r=rmin;r<=rmax;r+=1<<16)
for(b=c->bmin;b<=c->bmax;b++) for(b=c->bmin;b<=c->bmax;b++)
@ -471,10 +472,10 @@ VMIN:
if(to->table[r + g + b]) // OT_get if(to->table[r + g + b]) // OT_get
{ {
vmin=g; vmin=g;
goto VMAX; goto vmax;
} }
} }
VMAX: vmax:
for(g=c->vmax<<8;g>=vmin;g-=1<<8) for(g=c->vmax<<8;g>=vmin;g-=1<<8)
for(r=rmin;r<=rmax;r+=1<<16) for(r=rmin;r<=rmax;r+=1<<16)
for(b=c->bmin;b<=c->bmax;b++) for(b=c->bmin;b<=c->bmax;b++)
@ -521,7 +522,12 @@ ENDCRUSH:
c->rmin=rmin>>16; c->rmax=rmax>>16; c->rmin=rmin>>16; c->rmax=rmax>>16;
c->vmin=vmin>>8; c->vmax=vmax>>8; c->vmin=vmin>>8; c->vmax=vmax>>8;
c->bmin=bmin; c->bmax=bmax; c->bmin=bmin; c->bmax=bmax;
*/
c->rmin=rmin; c->rmax=rmax;
c->vmin=vmin; c->vmax=vmax;
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
// This multiplications are supposed to improve the result, but may or may not // This multiplications are supposed to improve the result, but may or may not
// work, actually. // work, actually.
@ -559,7 +565,133 @@ ENDCRUSH:
} }
} }
void Cluster_split(T_Cluster * c,T_Cluster * c1,T_Cluster * c2,int teinte,T_Occurrence_table * to)
{
int limite;
int cumul;
int r,v,b;
limite=(c->occurences)/2;
cumul=0;
if (teinte==0)
{
for (r=c->rmin;r<=c->rmax;r++)
{
for (v=c->vmin;v<=c->vmax;v++)
{
for (b=c->bmin;b<=c->bmax;b++)
{
cumul+=OT_get(to,r,v,b);
if (cumul>=limite)
break;
}
if (cumul>=limite)
break;
}
if (cumul>=limite)
break;
}
if (r==c->rmin)
r++;
// R est la valeur de début du 2nd cluster
c1->Rmin=c->Rmin; c1->Rmax=r-1;
c1->rmin=c->rmin; c1->rmax=r-1;
c1->Gmin=c->Gmin; c1->Vmax=c->Vmax;
c1->vmin=c->vmin; c1->vmax=c->vmax;
c1->Bmin=c->Bmin; c1->Bmax=c->Bmax;
c1->bmin=c->bmin; c1->bmax=c->bmax;
c2->Rmin=r; c2->Rmax=c->Rmax;
c2->rmin=r; c2->rmax=c->rmax;
c2->Gmin=c->Gmin; c2->Vmax=c->Vmax;
c2->vmin=c->vmin; c2->vmax=c->vmax;
c2->Bmin=c->Bmin; c2->Bmax=c->Bmax;
c2->bmin=c->bmin; c2->bmax=c->bmax;
}
else
if (teinte==1)
{
for (v=c->vmin;v<=c->vmax;v++)
{
for (r=c->rmin;r<=c->rmax;r++)
{
for (b=c->bmin;b<=c->bmax;b++)
{
cumul+=OT_get(to,r,v,b);
if (cumul>=limite)
break;
}
if (cumul>=limite)
break;
}
if (cumul>=limite)
break;
}
if (v==c->vmin)
v++;
// V est la valeur de début du 2nd cluster
c1->Rmin=c->Rmin; c1->Rmax=c->Rmax;
c1->rmin=c->rmin; c1->rmax=c->rmax;
c1->Gmin=c->Gmin; c1->Vmax=v-1;
c1->vmin=c->vmin; c1->vmax=v-1;
c1->Bmin=c->Bmin; c1->Bmax=c->Bmax;
c1->bmin=c->bmin; c1->bmax=c->bmax;
c2->Rmin=c->Rmin; c2->Rmax=c->Rmax;
c2->rmin=c->rmin; c2->rmax=c->rmax;
c2->Gmin=v; c2->Vmax=c->Vmax;
c2->vmin=v; c2->vmax=c->vmax;
c2->Bmin=c->Bmin; c2->Bmax=c->Bmax;
c2->bmin=c->bmin; c2->bmax=c->bmax;
}
else
{
for (b=c->bmin;b<=c->bmax;b++)
{
for (v=c->vmin;v<=c->vmax;v++)
{
for (r=c->rmin;r<=c->rmax;r++)
{
cumul+=OT_get(to,r,v,b);
if (cumul>=limite)
break;
}
if (cumul>=limite)
break;
}
if (cumul>=limite)
break;
}
if (b==c->bmin)
b++;
// B est la valeur de début du 2nd cluster
c1->Rmin=c->Rmin; c1->Rmax=c->Rmax;
c1->rmin=c->rmin; c1->rmax=c->rmax;
c1->Gmin=c->Gmin; c1->Vmax=c->Vmax;
c1->vmin=c->vmin; c1->vmax=c->vmax;
c1->Bmin=c->Bmin; c1->Bmax=b-1;
c1->bmin=c->bmin; c1->bmax=b-1;
c2->Rmin=c->Rmin; c2->Rmax=c->Rmax;
c2->rmin=c->rmin; c2->rmax=c->rmax;
c2->Gmin=c->Gmin; c2->Vmax=c->Vmax;
c2->vmin=c->vmin; c2->vmax=c->vmax;
c2->Bmin=b; c2->Bmax=c->Bmax;
c2->bmin=b; c2->bmax=c->bmax;
}
}
/*
/// 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,
@ -603,14 +735,14 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
c1->Rmin=c->Rmin; c1->Rmax=r-1; c1->Rmin=c->Rmin; c1->Rmax=r-1;
c1->rmin=c->rmin; c1->rmax=r-1; c1->rmin=c->rmin; c1->rmax=r-1;
c1->Gmin=c->Gmin; c1->Vmax=c->Vmax; c1->Gmin=c->Gmin; c1->vmax=c->vmax;
c1->vmin=c->vmin; c1->vmax=c->vmax; c1->vmin=c->vmin; c1->vmax=c->vmax;
c1->Bmin=c->Bmin; c1->Bmax=c->Bmax; c1->Bmin=c->Bmin; c1->Bmax=c->Bmax;
c1->bmin=c->bmin; c1->bmax=c->bmax; c1->bmin=c->bmin; c1->bmax=c->bmax;
c2->Rmin=r; c2->Rmax=c->Rmax; c2->Rmin=r; c2->Rmax=c->Rmax;
c2->rmin=r; c2->rmax=c->rmax; c2->rmin=r; c2->rmax=c->rmax;
c2->Gmin=c->Gmin; c2->Vmax=c->Vmax; c2->Gmin=c->Gmin; c2->vmax=c->vmax;
c2->vmin=c->vmin; c2->vmax=c->vmax; c2->vmin=c->vmin; c2->vmax=c->vmax;
c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; c2->Bmin=c->Bmin; c2->Bmax=c->Bmax;
c2->bmin=c->bmin; c2->bmax=c->bmax; c2->bmin=c->bmin; c2->bmax=c->bmax;
@ -643,14 +775,14 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; c1->Rmin=c->Rmin; c1->Rmax=c->Rmax;
c1->rmin=c->rmin; c1->rmax=c->rmax; c1->rmin=c->rmin; c1->rmax=c->rmax;
c1->Gmin=c->Gmin; c1->Vmax=g-1; c1->Gmin=c->Gmin; c1->vmax=g-1;
c1->vmin=c->vmin; c1->vmax=g-1; c1->vmin=c->vmin; c1->vmax=g-1;
c1->Bmin=c->Bmin; c1->Bmax=c->Bmax; c1->Bmin=c->Bmin; c1->Bmax=c->Bmax;
c1->bmin=c->bmin; c1->bmax=c->bmax; c1->bmin=c->bmin; c1->bmax=c->bmax;
c2->Rmin=c->Rmin; c2->Rmax=c->Rmax; c2->Rmin=c->Rmin; c2->Rmax=c->Rmax;
c2->rmin=c->rmin; c2->rmax=c->rmax; c2->rmin=c->rmin; c2->rmax=c->rmax;
c2->Gmin=g; c2->Vmax=c->Vmax; c2->Gmin=g; c2->vmax=c->vmax;
c2->vmin=g; c2->vmax=c->vmax; c2->vmin=g; c2->vmax=c->vmax;
c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; c2->Bmin=c->Bmin; c2->Bmax=c->Bmax;
c2->bmin=c->bmin; c2->bmax=c->bmax; c2->bmin=c->bmin; c2->bmax=c->bmax;
@ -682,20 +814,20 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; c1->Rmin=c->Rmin; c1->Rmax=c->Rmax;
c1->rmin=c->rmin; c1->rmax=c->rmax; c1->rmin=c->rmin; c1->rmax=c->rmax;
c1->Gmin=c->Gmin; c1->Vmax=c->Vmax; c1->Gmin=c->Gmin; c1->vmax=c->vmax;
c1->vmin=c->vmin; c1->vmax=c->vmax; c1->vmin=c->vmin; c1->vmax=c->vmax;
c1->Bmin=c->Bmin; c1->Bmax=b-1; c1->Bmin=c->Bmin; c1->Bmax=b-1;
c1->bmin=c->bmin; c1->bmax=b-1; c1->bmin=c->bmin; c1->bmax=b-1;
c2->Rmin=c->Rmin; c2->Rmax=c->Rmax; c2->Rmin=c->Rmin; c2->Rmax=c->Rmax;
c2->rmin=c->rmin; c2->rmax=c->rmax; c2->rmin=c->rmin; c2->rmax=c->rmax;
c2->Gmin=c->Gmin; c2->Vmax=c->Vmax; c2->Gmin=c->Gmin; c2->vmax=c->vmax;
c2->vmin=c->vmin; c2->vmax=c->vmax; c2->vmin=c->vmin; c2->vmax=c->vmax;
c2->Bmin=b; c2->Bmax=c->Bmax; c2->Bmin=b; c2->Bmax=c->Bmax;
c2->bmin=b; c2->bmax=c->bmax; c2->bmin=b; c2->bmax=c->bmax;
} }
} }
*/
/// Compute the mean R, G, B (for palette generation) and H, L (for palette sorting) /// Compute the mean R, G, B (for palette generation) and H, L (for palette sorting)
void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to) void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to)
@ -757,7 +889,7 @@ void CS_Init(T_Cluster_set * cs, T_Occurrence_table * to)
cs->clusters->Gmin = cs->clusters->vmin = 0; cs->clusters->Gmin = cs->clusters->vmin = 0;
cs->clusters->Bmin = cs->clusters->bmin = 0; cs->clusters->Bmin = cs->clusters->bmin = 0;
cs->clusters->Rmax = cs->clusters->rmax = to->rng_r - 1; cs->clusters->Rmax = cs->clusters->rmax = to->rng_r - 1;
cs->clusters->Vmax = cs->clusters->vmax = to->rng_g - 1; cs->clusters->vmax = cs->clusters->vmax = to->rng_g - 1;
cs->clusters->Bmax = cs->clusters->bmax = to->rng_b - 1; cs->clusters->Bmax = cs->clusters->bmax = to->rng_b - 1;
cs->clusters->next = NULL; cs->clusters->next = NULL;
Cluster_pack(cs->clusters, to); Cluster_pack(cs->clusters, to);
@ -1007,7 +1139,7 @@ void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table *
palette[index].B=current->b; palette[index].B=current->b;
for (r=current->Rmin; r<=current->Rmax; r++) for (r=current->Rmin; r<=current->Rmax; r++)
for (g=current->Gmin;g<=current->Vmax;g++) for (g=current->Gmin;g<=current->vmax;g++)
for (b=current->Bmin;b<=current->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; current = current->next;
@ -1338,8 +1470,6 @@ void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest,
// For some of them only the first one may work because of ugly optimizations // For some of them only the first one may work because of ugly optimizations
static const byte precision_24b[]= static const byte precision_24b[]=
{ {
8,8,8,
6,6,6,
6,6,5, 6,6,5,
5,6,5, 5,6,5,
5,5,5, 5,5,5,

View File

@ -49,7 +49,17 @@ Uint32 Airbrush_next_time;
void Start_operation_stack(word new_operation) void Start_operation_stack(word new_operation)
{ {
// This part handles things that must be done when exiting an operation.
Brush_rotation_center_is_defined=0; Brush_rotation_center_is_defined=0;
switch(Current_operation)
{
case OPERATION_ROTATE_BRUSH:
End_brush_rotation();
break;
default:
break;
}
// On mémorise l'opération précédente si on démarre une interruption // On mémorise l'opération précédente si on démarre une interruption
switch(new_operation) switch(new_operation)
@ -61,6 +71,7 @@ void Start_operation_stack(word new_operation)
case OPERATION_POLYBRUSH: case OPERATION_POLYBRUSH:
case OPERATION_STRETCH_BRUSH: case OPERATION_STRETCH_BRUSH:
case OPERATION_ROTATE_BRUSH: case OPERATION_ROTATE_BRUSH:
Begin_brush_rotation();
Operation_before_interrupt=Current_operation; Operation_before_interrupt=Current_operation;
// On passe à l'operation demandée // On passe à l'operation demandée
Current_operation=new_operation; Current_operation=new_operation;

View File

@ -1,2 +1,2 @@
char Program_version[]="2.3"; char Program_version[]="2.4wip";