圖形填充算法(掃描線種子填充算法)

好多天沒去上圖形學的課了,今天聽說要交幾個圖形學的算法實現程序,就花了將近一天的時間終於將程序調試通過了,可是到了實驗室,才知道老師根本沒時間檢查。哎,白寫了^_^.說笑了,其實不寫怎麼能真正理解算法的真諦呢。現在將程序貼出來,以備將來有學弟學妹之用。(其實如果只是Copy來的程序,對自己真是沒什麼用,除了有時能瞞過老師,也許對成績有幫助。僅此而已。)

/**
* 作者:老謝
* 最後修改日期:2006.4.14
* Email:[email protected]
* 功能描述:
* 圖形填充算法之
* 掃描線種子填充算法;
**/
/**
* 該程序還需要一個存儲 Point (點)結構的一個堆棧
* 和圖形模式的初始化程序
* 這兩個程序的實現程序在後面
**/

/*linescan.c*/

#include "graphics.h"
#include "dos.h"
#include "stdio.h"
#include "PStack.h"

/**
* 初始化掃描線
* (x,y)必須在圖形的內部
**/
void initScan(PointStack *s,int x,int y)
{
 Point p;

 p.X = x;
 p.Y = y;

 push(s,p);

 delay(4000);
}

/**
* 根據種子填充這一行,並且找到上下兩行的種子,入棧
**/
void fillThisLine(PointStack *s,Point seed,color fillColor,color borderColor)
{
 int curx = seed.X;
 int cury = seed.Y;

 int xr = 0;
 int xl = 0;

 int tag = 0; /*分別爲區段的左右座標值*/
 Point point;

 curx = seed.X;

 /**
 * 不是邊界 也沒有填充過,一直向右走
 **/
 while(getpixel(curx,cury) != borderColor &&
  getpixel(curx,cury) != fillColor)
 {
  if(curx > 600)
  {
   printf("curx = %d",curx);
   return;
  }

  curx++;
 }

 xr = --curx;

 /**
 * 開始向左填充
 **/
 while(getpixel(curx,cury) != borderColor &&
  getpixel(curx,cury) != fillColor)
 {
  putpixel(curx,cury,fillColor);

  if(curx <= 0)
  {
   /*座標越界*/
   printf("curx = %d /n",curx);
   return;
  }
  curx--;
 }

 xl = ++curx;

 /**
 //從左邊開始檢查y-1這一行,直到遇到邊界或者已經填充過的點,記錄,作爲種子
 //繼續檢查直到檢查到Xr;
 **/
 tag = 0;/*初始值必須是0*/
 curx = xl;
 while(curx <= xr)
 {
  /*發現空白並標記(tag = 1)*/
  if(getpixel(curx,cury-1) != borderColor &&
   getpixel(curx,cury-1) != fillColor)
  {
   tag = 1; /*有空白點*/
  }
  else
  {
   /**
   * 有空白點纔有種子
   * 空白結束,保存種子,並清空標記
   **/
   if(tag == 1)
   {
    curx--;
    point.X = curx;
    point.Y = cury-1;
    push(s,point);

    /*一段空白只能有一個種子*/
    tag = 0;
   }
  }
  curx++;
 }
 if(tag == 1)
 {
  curx--;
  point.X = curx;
  point.Y = cury-1;
  push(s,point);
 }
 /**
 //從左邊開始檢查y+1這一行,直到遇到邊界或者已經填充過的點,記錄,作爲種子
 //繼續檢查直到檢查到Xr;
 **/
 curx = xl;
 tag = 0;/*初始值必須是0*/
 while(curx <= xr)
 {
  /*發現空白並標記(tag = 1)*/
  if(getpixel(curx,cury+1) != borderColor &&
   getpixel(curx,cury+1) != fillColor)
  {
   tag = 1; /*有空白點*/
  }
  else
  {
   /**
   * 有空白點纔有種子
   * 空白結束,保存種子,並清空標記
   **/
   if(tag == 1)
   {
    curx--;
    point.X = curx;
    point.Y = cury+1;
    push(s,point);

    /*一段空白只能有一個種子*/
    tag = 0;
   }
  }
  curx++;
 }
 if(tag == 1)
 {

  curx--;
  point.X = curx;
  point.Y = cury+1;
  push(s,point);
 }

}

/**
* 用指定顏色填充指定區域(並且指定所用的 stack)
**/
void fill(PointStack *s,color fillColor,color borderColor)
{
 Point seed;

 while(s->length > 0)
 {
  seed = pop(s);
  fillThisLine(s,seed,fillColor,borderColor);
 }
}

/**
* 應用實例
**/
int main()
{
 Point p;

 PointStack s;

 initstack(&s);
 init();

 printf("Start!");
 getch();
 circle(200,200,100);
 circle(200,200,30);
 circle(200,150,25);
 circle(200,170,20);
 rectangle(150,210,250,250);

 getch();

 initScan(&s,245,201);
 fill(&s,RED,WHITE);
 destroy(&s);

 initScan(&s,201,199);
 fill(&s,GREEN,WHITE);
 destroy(&s);

 initScan(&s,201,151);
 fill(&s,3,WHITE);
 destroy(&s);

 initScan(&s,201,139);
 fill(&s,9,WHITE);
 destroy(&s);

 initScan(&s,249,249);
 fill(&s,13,WHITE);
 destroy(&s);

 printf("Length of stackt:%d/n",s.length);
 printf("Capacity of stackt:%d/n",s.capacity);

 getch();
 closegraph();
}

/*PStack.H*/
/*******************堆棧的聲明******************************/
/**
* 定義一個存放Piont 結構的堆棧(動態數組實現)
**/
#ifndef POINTSTACK_H
#define POINTSTACK_H

#include "stdio.h"
#include "stdlib.h"

/**
* define the Point struct
**/
typedef struct
{
 int X;
 int Y;
}Point;
/**
*stack
**/
typedef struct
{
 Point * head;
 int length;
 int capacity;
}PointStack;

/*========================*/
bool initstack(PointStack *s);
void destroy(PointStack *s);
void push(PointStack *s,Point p);
Point pop(PointStack *s);

#endif

/*PStack.c*/
/**
* 定義一個存放Piont 結構的堆棧(動態數組實現)
**/
#include "myhead.h"
#include "PStack.h"

/*當堆棧空時返回*/
Point NPoint;

/*初始化堆棧*/
bool initstack(PointStack * s)
{
 NPoint.X = -1;
 NPoint.Y = -1;
 
 s->length = 0;
 s->capacity = 20;

 /*Capacity*/
 s->head = (Point *)malloc(sizeof(Point)*20);
 if(s->head == null)
 {
  printf("malloc error!");
  exit(0);
 }
 return true;
}

void destroy(PointStack *s)
{
 free(s->head);
 s->length = 0;
 s->capacity = 0;
}

void push(PointStack *s,Point p)
{
 Point * temp;
 int i;

 if(s->length >= s->capacity)
 {
  temp = (Point *)malloc(sizeof(Point)*(s->capacity + 20));
  if(temp != null)
  {
   /*success*/
   for(i = 0;i < s->length;i++)
   {
    temp[i] = s->head[i];
   }

   s->capacity += 20;
   free(s->head);
   s->head = temp;
  }
  else
  {
   printf("malloc error!=n");
   exit(0);
  }
 }

 /*push*/
 s->head[s->length] = p;
 s->length++;
}

Point pop(PointStack *s)
{
 Point temp;

 if(s->length == 0)
 {
  return 0;
 }
 else
 {
  s->length--;
  temp = s->head[s->length];
  return temp;
 }
}

/*myhead.c*/
/*圖形模式初始化*/
int init()
{
 int  driver = DETECT,mode = 0;
 initgraph(&driver,&mode,"E://tc//tc2");
 return 1;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章