home *** CD-ROM | disk | FTP | other *** search
-
- /* This module keeps track of which pixels are calculated and which are
- * not. It then returns the next pixel to start from, which is
- * guaranteed to be in upper edge of an area.
- * The algorithm used here depends on that the chain of pixels relayed
- * to it 1) goes clockwise and 2) follows the boundary of the area
- * (That is, no peaks to the inside) (That would be stupid anyways)
- */
-
- /* In case you are interested, the changes in the "calculated-or-not"
- * status (off-to-on and on-to-off) are stored in a column by column
- * basis in a dynamically allocated structure.
- */
-
- /* NOTE: This module is used both by the sender and the receiver, since
- * pixel position information are omitted; the receiver should
- * reconstruct it using this package.
- * (unless FAST-flag is used)
-
- * void initialize(int nx, int ny);
- * void deinit(void);
- * int first_point(int *nx, int *ny);
- * void next_point(int dir);
-
- */
-
- #include <stdio.h>
- #include "mb.h"
-
- #undef DEBUG
-
- #define DEFSIZE 8
- typedef struct {
- int *ch;
- int size;
- } pixline;
- static pixline *pix;
- static int px, py;
- static int xsize, ysize;
- static int firstdir, prevdir;
- #define NONE -1
- #define FIRSTP 0
- #define NEXTP 1
- static int prevcall;
- static int firstx, lastx;
-
- #define NOP 0
- #define ON 1
- #define OFF 2
- /* The need for on-to-off or off-to-on -transitions is determined
- * entirely by previous and current direction. */
- static int dir_code[4][4]= {
- {NOP, ON, ON, NOP},
- {NOP, ON, ON, ON|OFF},
- {OFF, NOP, NOP, OFF},
- {OFF, ON|OFF, NOP, OFF}};
-
-
- /* dynamically allocate array */
- void initialize(nx, ny)
- int nx, ny;
- {
- int x;
- xsize= nx; ysize= ny;
- pix= (pixline *)malloc(xsize * sizeof(pixline));
- for (x= 0; x < xsize; x++) {
- pix[x].ch= (int *)malloc(DEFSIZE * sizeof(int));
- pix[x].size= DEFSIZE;
- }
- for (x= 0; x < xsize; x++) {
- pix[x].ch[0]= 0; /* first on-to-off transition */
- pix[x].ch[1]= -1; /* end of pixline */
- }
- prevcall= NONE;
- }
-
-
- /* free it as needed */
- void deinit()
- {
- int x;
- for (x= 0; x < xsize; x++)
- free(pix[x].ch);
- free(pix);
- }
-
-
- /* return next starting point for the crawling algorithm (or 0) */
- int first_point(nx, ny)
- int *nx, *ny;
- {
- int x, y1, y2;
- void next_point();
-
- /* There are at least two special cases to be considered.
- * 1) If first_point() is called two times in a row (that is, no
- * next_point() in between) that means that the previous area
- * consisted only of one single point. This is easily fixed by
- * feeding next_point() some false input.
- */
- if (prevcall == FIRSTP) {
- prevdir= RIGHT;
- next_point(LEFT);
- }
- /* 2) Assume next_point() has been called. The first direction in the
- * chain had to be wrapped to the end, because it's predecessor
- * of all pixels has to be known. Now handle that first dir.
- */
- else if (prevcall == NEXTP)
- next_point(firstdir);
-
- prevcall= FIRSTP; /* Now it is us that was the previously called one */
-
- /* first remove redundancy from the pix array (that is, if in the
- * same pixel position is both on-to-off and off-to-on -transition,
- * discard both. */
- #ifdef DEBUG
- printf ("--------------------------------------\ncombining...\n");
- #endif
- for (x= firstx; x <= lastx; x++) {
- #ifdef DEBUG
- if (pix[x].ch[0] != 0 || pix[x].ch[1] != -1) {
- int y;
- printf ("Line %d (len %d):",x, pix[x].size);
- for (y= 0; ; y++) {
- printf ("%d ", pix[x].ch[y]);
- if (pix[x].ch[y] < 0)
- break;
- }
- printf ("\n");
- }
- #endif
- for (y1= y2= 0; ; y1++, y2++) {
- while (pix[x].ch[y1] >= 0 &&
- pix[x].ch[y1] == pix[x].ch[y1+1])
- y1 += 2;
- pix[x].ch[y2]= pix[x].ch[y1];
- if (pix[x].ch[y1] < 0) break;
- }
- #ifdef DEBUG
- if (pix[x].ch[0] != 0 || pix[x].ch[1] != -1) {
- int y;
- printf ("Line %d (len %d):",x, pix[x].size);
- for (y= 0; ; y++) {
- printf ("%d ", pix[x].ch[y]);
- if (pix[x].ch[y] < 0)
- break;
- }
- printf ("\n");
- }
- #endif
- }
-
- px= 0; py= pix[0].ch[0];
- for (x= 1; x < xsize; x++)
- if (pix[x].ch[0] < py) {
- py= pix[x].ch[0];
- px= x;
- }
- *nx= px; *ny= py;
- firstx= xsize; lastx= 0;
- prevdir= NODIR;
- if (py >= ysize) return(0);
- return(1);
- }
-
-
- void next_point(dir)
- int dir;
- {
- int y;
- int code;
- if (prevdir == NODIR) {
- /* This is the first dir in the chain. Because we do not
- * know the previous dir, wrap this one to the end of the chain,
- * since then we do know it. */
- code= NOP;
- firstdir= dir;
- }
- else
- code= dir_code[prevdir][dir];
-
- #ifdef DEBUG
- printf ("prev= %d dir= %d -> %d\n", prevdir, dir, code);
- printf ("Line %d (len %d):",px, pix[px].size);
- for (y= 0; ; y++) {
- printf ("%d ", pix[px].ch[y]);
- if (pix[px].ch[y] < 0)
- break;
- }
- printf ("\n");
- #endif
-
- /* Optimize a little.. keep track of which lines need to be rearranged
- */
- if (px < firstx) firstx= px;
- if (px > lastx) lastx= px;
-
- /* Store on-to-off and off-to-on transitions in an uniform manner
- * (The only exception is that on-to-off is stored one pixel below)
- */
- if (code & ON) {
- int tmp1= py, tmp2;
- y= 0;
- while (pix[px].ch[y] < tmp1 && pix[px].ch[y] >= 0)
- y++;
- while (tmp1 >= 0) {
- tmp2= pix[px].ch[y];
- pix[px].ch[y]= tmp1;
- tmp1= tmp2;
- y++;
- }
- if (y >= pix[px].size)
- pix[px].ch= (int *)realloc(pix[px].ch,
- (pix[px].size += DEFSIZE) * sizeof(int));
- pix[px].ch[y]= tmp1; /* == -1 */
- }
-
- if (code & OFF) {
- int tmp1= py+1, tmp2;
- y= 0;
- while (pix[px].ch[y] < tmp1 && pix[px].ch[y] >= 0)
- y++;
- while (tmp1 >= 0) {
- tmp2= pix[px].ch[y];
- pix[px].ch[y]= tmp1;
- tmp1= tmp2;
- y++;
- }
- if (y >= pix[px].size)
- pix[px].ch= (int *)realloc(pix[px].ch,
- (pix[px].size += DEFSIZE) * sizeof(int));
- pix[px].ch[y]= tmp1; /* == -1 */
- }
-
- #ifdef DEBUG
- printf ("Line %d (len %d):",px, pix[px].size);
- for (y= 0; ; y++) {
- printf ("%d ", pix[px].ch[y]);
- if (pix[px].ch[y] < 0)
- break;
- }
- printf ("\n\n");
- #endif
-
- switch (dir) {
- case UP: py--; break;
- case DOWN: py++; break;
- case LEFT: px--; break;
- case RIGHT: px++; break;
- }
- prevdir= dir;
- prevcall= NEXTP;
- }
-
-