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:
parent
1da0c96db8
commit
2d8c061e32
110
src/brush.c
110
src/brush.c
@ -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));
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
172
src/op_c.c
172
src/op_c.c
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
char Program_version[]="2.3";
|
char Program_version[]="2.4wip";
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user