帖一段EC中的种子填充代码,网友曾庆伟的作品,希望对你有用:
/* 预定义位置堆栈的大小。100已经是一个很大的数值了,通常不会溢出 */
#ifndef FILL_STACK
#define FILL_STACK 100
#endif
struct point
{
int x;
int y;
};
/* 申请种子填充需要的位置堆栈 */
struct point *call_fill_stack()
{
int i;
struct point *mem = (struct point *)calloc(FILL_STACK, sizeof(struct point));
if(mem == NULL)
{
message(3, svga_info);
}
else
{
for(i=0; i<FILL_STACK; i++)
{
mem[i].x = mem[i].y = -1;
}
}
return(mem);
}
/* 处理每行的操作 */
void fill_process_row(int y , int mode)
{
signed long begin = position(0, y);
if(mode == COPY_GET)
{
one_row(get, border_get, &begin, y, SYS.SEG, SYS.OFF, SYS.LENGTH_OF_ROW);
}
else if(mode == COPY_PUT)
{
one_row(put, border_put, &begin, y, SYS.SEG, SYS.OFF, SYS.LENGTH_OF_ROW);
}
else
{
return;
}
}
/* 探测相邻行是否需要填充,需要的话,把每个区段的最右侧的点压入堆栈 */
void fill_detect(int left, int right, int y, BITS fill_color, BITS edge_color,
struct point max[], int *count)
{
int i;
int flag = 0; /* 0表示从边界恢复,1表示从填充区到达边界 */
if(left<0 || right<0)
{
return;
}
for(i=left; i<=right; i++)
{
if(memcmp(RB+i*PL, edge_color, PL) && memcmp(RB+i*PL, fill_color, PL))
{
flag = 1;
}
else
{
if(flag == 1)
{
(*count)++;
if(*count > FILL_STACK)
{
message(3, svga_info);
*count = -1;
return;
}
else
{
max[*count].x = i-1;
max[*count].y = y;
}
}
flag = 0;
}
}
if(flag == 1)
{
(*count)++;
max[*count].x = right;
max[*count].y = y;
}
}
/* 填充特定行,并将其上下行每段的最右位置写入数组max,作为待填充标志 */
void fill_row(struct point max[], int *count, BITS fill_color, BITS edge_color)
{
int left = 0, right = 0;
int i;
int y = max[*count].y, x = max[*count].x;
if(x<0 || x>SYS.MAX_X || y<0 || y>SYS.MAX_Y)
{
(*count)--;
return;
}
fill_process_row(y, COPY_GET);
/* 检测初始点,如果是边界色或者填充色,直接退出 */
if(memcmp(RB+x*PL, edge_color, PL) && memcmp(RB+x*PL, fill_color, PL))
{
memcpy(RB+x*PL, fill_color, PL);
}
else
{
(*count)--;
return;
}
/* 从初始点向两侧检测边界 */
for(i=x-1; i>=0; i--)
{
if(memcmp(RB+i*PL, edge_color, PL) && memcmp(RB+i*PL, fill_color, PL))
{
memcpy(RB+i*PL, fill_color, PL);
}
else
{
left = i + 1;
break;
}
}
if(i == -1)
{
left = 0;
}
for(i=x+1; i<=SYS.MAX_X; i++)
{
if(memcmp(RB+i*PL, edge_color, PL) && memcmp(RB+i*PL, fill_color, PL))
{
memcpy(RB+i*PL, fill_color, PL);
}
else
{
right = i - 1;
break;
}
}
if(i == SYS.MAX_X+1)
{
right = SYS.MAX_X;
}
fill_process_row(y, COPY_PUT);
(*count)--;
/* 检测本行的上下行,在left到right范围内看是否有需要填充的区段 */
if(y == 0)
{
fill_process_row(y+1, COPY_GET);
fill_detect(left, right, y+1, fill_color, edge_color, max, count);
}
else if(y == SYS.MAX_Y)
{
fill_process_row(y-1, COPY_GET);
fill_detect(left, right, y-1, fill_color, edge_color, max, count);
}
else
{
fill_process_row(y-1, COPY_GET);
fill_detect(left, right, y-1, fill_color, edge_color, max, count);
fill_process_row(y+1, COPY_GET);
fill_detect(left, right, y+1, fill_color, edge_color, max, count);
}
}
/* 从指定的位置开始填充一定的区域。遇到填充色或边界色停止。 */
/* 出于稳定性的考虑,目前这个版本占用内存很低,速度较慢。 */
int fill(UINT x, UINT y, BITS fill_color, BITS edge_color)
{
int count;
struct point *max = call_fill_stack();
if(max == NULL)
{
return(FAIL);
}
else
{
count = 0;
max[0].x = x;
max[0].y = y;
}
while(count >= 0)
{
fill_row(max, &count, fill_color, edge_color);
}
free(max);
return(GOOD);
}