home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3406
/
pix.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-23
|
6KB
|
256 lines
/* 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;
}