home *** CD-ROM | disk | FTP | other *** search
File List | 1987-02-06 | 12.2 KB | 483 lines |
- /* Listing one */
- /* Subroutines for converting a pixel image
- to a quadtree and output the quadtree as
- locational codes
-
- Written by: Ronald G. White
-
- External routines:
- px2quad - only entry point
- */
-
- #include <stdio.h>
-
- /* Define structure for each node */
- typedef struct qnode {
- struct qnode *child[4]; /* pointers to each child */
- struct qnode *next; /* used during output */
- int color;
- int ntype; /* see below for types */
- int locode; /* location code */
- } QNODE, *PNODE;
-
- /* Node types: */
- #define LEAF 1 /* no children */
- #define BLEND 2 /* color of >2 kids */
- #define WASH 3 /* color irrelevent */
-
- extern getpix(); /* return pixel color at given posn */
- extern putllc(); /* output location code and color */
-
- static int toplevel; /* top level of tree (root node) */
-
- px2quad(size)
- int size;
- /* entry point for these routines. Control routine to
- create a quadtree from the pixel image and output it
- as locational codes
-
- input:
- size - size of the image rounded up to nearest
- power of two
- */
-
- {
- PNODE crtnode(), proot;
-
- /* Create the root node */
- proot = crtnode();
-
- /* Calculate the toplevel number */
- toplevel = 0;
- while (size > 1) {
- toplevel++;
- size >>= 1; /* divide by two */
- }
-
- /* Build the quad tree */
- proot->locode = 1;
- addnode(proot, toplevel);
-
- /* Output it as location codes */
- outtree(proot);
- }
-
- static PNODE crtnode()
- /* create a quadtree node and initialize it
-
- output:
- returns a pointer to the node
- */
- {
- int i;
- PNODE newnode;
-
- /* Get space for it */
- newnode = (PNODE) malloc(sizeof(QNODE));
- if (newnode == NULL) {
- /* Something went wrong */
- fprintf(stderr,
- "crtnode: malloc failure; unable to continue0);
- exit(1);
- }
-
- /* Initialize it */
- for (i = 0; i < 4; i++) {
- newnode->child[i] = NULL;
- }
- newnode->color = 0;
- newnode->ntype = LEAF;
- return(newnode);
- }
-
- static addnode(pnode, level)
- int level;
- PNODE pnode;
- /* add a new node to the quad tree
- If the node is not at the bottom level, four child
- nodes are created and added below the current node.
- Otherwise the node color is set to that of the
- corresponding pixel.
-
- input:
- pnode - pointer to the current node
- level - level number of the current node
- */
-
- {
- int i;
- int newlevel;
- PNODE crtnode(), newchild;
-
- /* if this node is not at the bottom level,
- * add four children below this node
- */
- if (level > 0) {
- newlevel = level - 1;
- for (i = 0; i < 4; i++) {
- newchild = crtnode();
- pnode->child[i] = newchild;
- newchild->locode = (pnode->locode << 2) + i;
- addnode(newchild, newlevel);
- }
-
- /* Remove any unnecessary children */
- condense(pnode);
-
- /* bottom level; get actual pixel color */
- } else {
- pnode->color = getcolor(pnode->locode);
- }
- }
-
- static condense(pnode)
- PNODE pnode;
- /* examine children of the current node and
- remove any that are unnecessary
-
- input:
- pnode - pointer to current node
- */
-
- {
- int colcnt[4];
- int colors[4];
- int i, j;
- int maxclr = 0;
- int nkids;
- int childclr;
- PNODE pchild;
-
- /* Initialization */
- for (i = 0; i < 4; i++) {
- colcnt[i] = 0;
- }
-
- /* Determine colors of children */
- for (i = 0; i < 4; i++) {
- pchild = pnode->child[i];
- if (pchild->ntype == WASH) {
- /* this child has no color */
- continue;
- }
-
- childclr = pchild->color;
-
- /* loop through colors found so far:
- do we have a match?
- note: we'll always "break" out of
- this loop because there can be at
- most four different colors.
- */
-
- for (j = 0; j < 4; j++) {
- if (colcnt[j] == 0) {
- /* new color */
- colors[j] = childclr;
- colcnt[j] = 1;
- break;
-
- } else if (childclr == colors[j]) {
- /* existing color */
- colcnt[j]++;
- if (colcnt[j] > colcnt[maxclr]) {
- maxclr = j;
- }
- break;
- }
- }
- }
-
- /* Set node color */
- pnode->color = colors[maxclr];
-
- /* Remove redundant children -- if more than
- one child node has the same color as the
- current node, then it contains redundant
- information. If the redundant node is a
- leaf node, it can just be removed. If it
- is not a leaf node, mark it as a WASH type
- and ignore it during output.
- */
-
- nkids = 4;
- if (colcnt[maxclr] > 1) {
- /* Loop through the four children */
- for (i = 0; i < 4; i++) {
- pchild = pnode->child[i];
-
- /* If child node is already a WASH,
- nothing else can be done to it
- */
- if (pchild->ntype == WASH) {
- continue;
- }
-
- childclr = pchild->color;
-
- /* Check for color match */
- if (childclr == pnode->color) {
-
- /* If child is leaf, release */
- if (pchild->ntype == LEAF) {
- relnode(pchild);
- pnode->child[i] = NULL;
- nkids--;
-
- /* otherwise, mark it as a WASH */
- } else {
- pchild->ntype = WASH;
- }
- }
- }
- }
-
- /* Reset node type -- a LEAF node has no children */
- if (nkids == 0) {
- pnode->ntype = LEAF;
-
- /* A BLEND node has a color that represents some
- missing children, but still has some other
- children that are a different color.
- */
- } else if (colcnt[maxclr] > 1) {
- pnode->ntype = BLEND;
-
- /* A WASH node is necessary in the quadtree because
- it points to existent children nodes, but will not
- be output because its information (i.e. color) is
- available either in child nodes or parent nodes.
- */
- } else {
- pnode->ntype = WASH;
- }
- }
-
- relnode(pnode)
- PNODE pnode;
- /* release a node
-
- input:
- pnode - pointer to node to release
- */
- {
- free((char *) pnode);
- }
-
- static getcolor(lcode)
- int lcode;
- /* get the color of the pixel corresponding to a
- bottom level node whose position is given by a
- locational code
-
- input:
- lcode - locational code of bottom level node
-
- output:
- returns pixel color
- */
- {
- int dir;
- int col = 0;
- int level;
- int row = 0;
- int shift;
-
- /* Convert node locational code to pixel row & column
- by looping through direction codes in locational
- code for each level from top to bottom
- */
- for (level = toplevel; level > 0; level--) {
-
- /* shift last row & col values left one bit */
- col <<= 1;
- row <<= 1;
-
- /* calculate the position of the direction
- code for this level and extract it
- */
- shift = (level - 1) * 2;
- dir = (lcode >> shift) & 0x3;
-
- /* increment the col value if quadrant is in
- left half, i.e. NE or SE child
- */
- if (dir == 1 || dir == 3) {
- col++;
- }
-
- /* increment the row value if quadrant is in
- bottom half, i.e. SW or SE child
- */
- if (dir == 2 || dir == 3) {
- row++;
- }
- }
-
- /* return pixel color */
- return(getpix(col, row));
- }
-
- static outtree(proot)
- PNODE proot;
- /* output the relevant nodes in the quad tree
- *
- * proot - pointer to the root node
- */
- {
- PNODE outnode(), pcur, plast;
-
- /* Set up the linked list with root node */
- pcur = proot;
- plast = proot;
- proot->next = NULL;
-
- /* Output each node on the linked list in order
- until there are no more nodes on the list
- */
- while (pcur != NULL) {
- plast = outnode(pcur, plast);
- pcur = pcur->next;
- }
- }
-
- static PNODE outnode(pnode, plast)
- PNODE pnode, plast;
- /* output the locational code and color index for a
- node and put its children on the list
-
- input:
- pnode - pointer to node to output
- plast - pointer to last node on the linked list
-
- output:
- returns pointer to new last node on linked list
- */
- {
- int i;
- PNODE pchild;
-
- /* If node is not a WASH, output it */
- if (pnode->ntype != WASH) {
- putlcc(pnode->locode, pnode->color);
- }
-
- /* Put the node's children on list */
- if (pnode->ntype != LEAF) {
- for (i = 0; i < 4; i++) {
- pchild = pnode->child[i];
- if (pchild != NULL) {
- plast->next = pchild;
- plast = pchild;
- }
- }
- }
-
- /* Return new last pointer */
- return(plast);
- }
-
-
-
-
-
- /* Listing two */
- /* Subroutines for displaying an image from a quadtree
- input as locational codes
-
- Written by: Ronald G. White
-
- External routines:
- qdisp - only entry point
-
- */
-
- #include <stdio.h>
-
- extern getnxn(); /* read in next node's data */
- extern filrec(); /* fill rectangular region */
-
- static int orgsize; /* original image size */
-
- qdisp(size)
- int size;
- /* main entry point for the display of a quadtree
- *
- * input:
- * size - size of the original image
- */
- {
- int lcode, color;
- int corner[2];
- int side;
-
- /* Make the image size global */
- orgsize = size;
-
- /* Read and display each node */
- while (getnxn(&lcode, &color) != EOF) {
-
- /* Convert loc code to corners, side of square */
- square(lcode, corner, &side);
-
- /* Fill in the square */
- filrec(corner[0], corner[1], side, side, color);
- }
- }
-
- square(lcode, corner, pside)
- int lcode;
- int corner[2];
- int *pside;
- /* convert quadtree locational code to corner and side
- of the square represented by the corresponding node.
-
- input:
- lcode - locational code for this node
-
- output:
- corner - upper left corner of quadrant
- pside - the size of the quadrant in pixels
- */
- {
- int dir;
- int shift;
-
- corner[0] = corner[1] = 0;
- *pside = orgsize;
-
- /* Find the begining of the code */
- for (shift = 30;
- ((lcode >> shift) & 0xff) == 0; shift -= 2);
-
- /* Convert node locational code to corner row &
- column by looping through direction codes in
- locational code for each level from top down.
- */
- for (shift -= 2; shift >= 0; shift -= 2) {
-
- /* The side of the square is reduced by a
- factor of two each level down.
- */
- *pside >>= 1;
-
- /* extract the direction code */
- dir = (lcode >> shift) & 0x3;
-
- /* increment the col value if quadrant is
- in left half, i.e. NE or SE child
- */
- if (dir == 1 || dir == 3) {
- corner[0] += *pside;
- }
-
- /* increment the row value if quadrant is
- in bottom half, i.e. SW or SE child
- */
- if (dir == 2 || dir == 3) {
- corner[1] += *pside;
- }
- }
- }
-