home *** CD-ROM | disk | FTP | other *** search
- /*
- * pccfctde.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* PCCFCTDE: functions for PCC decoding
- * (encoding functions in PCCFCT; and functions common
- * to both encoding and decoding programs in PCCFCT2)
- * FUNCTIONS:
- * PCCREAD, PCCDECODES, PCCDECODE, PCCDETRACK, PCC2XY
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <images.h> /* images file information */
- #include "pcc2.h" /* header file for PCC programs */
-
- int deCode[NDECODE]; /* decode table */
- extern unsigned char *fcCode; /* code storage */
- extern long nByteCode; /* no. bytes in storage */
-
-
- /* PCCREAD: function reads PCC code from file
- * usage: pccread (filename, &pcc, &nCode, &widthI, &heightI)
- *
- */
-
- #define TYPE_STRING 9 /* string for PCC image type */
-
- pccread (filename, pcc, nCode, widthI, heightI)
- char *filename;
- unsigned char **pcc; /* PCC code */
- long *nCode; /* no. bytes of code */
- long *widthI, *heightI; /* image size */
- {
- FILE *fpIn;
- unsigned char type[TYPE_STRING];
- char string1[20], string2[20];
- static char *typePCC = "TYPE=PCC";
- long w, h;
-
- /* open input PCC file */
- if ((fpIn = fopen (filename, "rb")) == NULL) {
- printf ("PCCREAD: cannot open file %s\n", filename);
- return (-1);
- }
-
- /* read PCC file header */
- fscanf (fpIn, "%8s", &type);
- //fscanf (fpIn, "%5s %5s %ld %ld", string1, string2, widthI, heightI);
- fscanf (fpIn, "%5s %5s %ld %ld", string1, string2, &w, &h);
- *widthI = w;
- *heightI = h;
- fscanf (fpIn, "%3s %7s %ld\n", string1, string2, nCode);
-
- if ((strcmp (type, typePCC)) != 0) {
- printf ("PCCREAD: input file is not in PCC format.", 1);
- return (-2);
- }
-
- if (((*pcc) = (unsigned char *) malloc (*nCode)) == NULL) {
- printf ("MALLOC: not enough memory -- sorry", 1);
- return (-3);
- }
- fread ((*pcc), sizeof (unsigned char), *nCode, fpIn);
-
- fclose (fpIn);
- return (0);
- }
-
-
-
- /* PCCDECODES: function constructs table of PCC decodes
- * corresponding to sequences of 0, 1, 2, or 3
- * direction vectors and features endpoint, bifurcation,
- * and cross
- * usage: pccdecodes ()
- * extern int decode;
- *
- */
-
- int deCode[NDECODE]; /* decode table */
-
- pccdecodes ()
- {
- /* CODE TO PACKED DIRECTION SEGMENTS TABLE */
-
- deCode[1] = 0000;
- deCode[2] = 0100;
- deCode[3] = 0200;
- deCode[4] = 0600;
- deCode[5] = 0700;
- deCode[6] = 0010;
- deCode[7] = 0110;
- deCode[8] = 0210;
- deCode[9] = 0310;
- deCode[10] = 0710;
- deCode[11] = 0020;
- deCode[12] = 0120;
- deCode[13] = 0220;
- deCode[14] = 0320;
- deCode[15] = 0060;
- deCode[16] = 0560;
- deCode[17] = 0660;
- deCode[18] = 0760;
- deCode[19] = 0070;
- deCode[20] = 0170;
- deCode[21] = 0570;
- deCode[22] = 0670;
- deCode[23] = 0770;
- deCode[24] = 0001;
- deCode[25] = 0201;
- deCode[26] = 0101;
- deCode[27] = 0601;
- deCode[28] = 0701;
- deCode[29] = 0011;
- deCode[30] = 0111;
- deCode[31] = 0211;
- deCode[32] = 0311;
- deCode[33] = 0711;
- deCode[34] = 0021;
- deCode[35] = 0121;
- deCode[36] = 0221;
- deCode[37] = 0321;
- deCode[38] = 0421;
- deCode[39] = 0131;
- deCode[40] = 0231;
- deCode[41] = 0331;
- deCode[42] = 0431;
- deCode[43] = 0531;
- deCode[44] = 0071;
- deCode[45] = 0171;
- deCode[46] = 0571;
- deCode[47] = 0671;
- deCode[48] = 0771;
- deCode[49] = 0002;
- deCode[50] = 0102;
- deCode[51] = 0202;
- deCode[52] = 0702;
- deCode[53] = 0012;
- deCode[54] = 0112;
- deCode[55] = 0212;
- deCode[56] = 0312;
- deCode[57] = 0712;
- deCode[58] = 0022;
- deCode[59] = 0122;
- deCode[60] = 0222;
- deCode[61] = 0322;
- deCode[62] = 0422;
- deCode[63] = 0132;
- deCode[64] = 0232;
- deCode[65] = 0332;
- deCode[66] = 0432;
- deCode[67] = 0532;
- deCode[68] = 0242;
- deCode[69] = 0342;
- deCode[70] = 0442;
- deCode[71] = 0542;
- deCode[72] = 0013;
- deCode[73] = 0113;
- deCode[74] = 0213;
- deCode[75] = 0313;
- deCode[76] = 0713;
- deCode[77] = 0023;
- deCode[78] = 0123;
- deCode[79] = 0223;
- deCode[80] = 0323;
- deCode[81] = 0423;
- deCode[82] = 0133;
- deCode[83] = 0233;
- deCode[84] = 0333;
- deCode[85] = 0433;
- deCode[86] = 0533;
- deCode[87] = 0243;
- deCode[88] = 0343;
- deCode[89] = 0443;
- deCode[90] = 0543;
- deCode[91] = 0643;
- deCode[92] = 0353;
- deCode[93] = 0453;
- deCode[94] = 0553;
- deCode[95] = 0653;
- deCode[96] = 0753;
- deCode[97] = 0124;
- deCode[98] = 0224;
- deCode[99] = 0324;
- deCode[100] = 0424;
- deCode[101] = 0134;
- deCode[102] = 0234;
- deCode[103] = 0334;
- deCode[104] = 0434;
- deCode[105] = 0534;
- deCode[106] = 0244;
- deCode[107] = 0344;
- deCode[108] = 0444;
- deCode[109] = 0544;
- deCode[110] = 0644;
- deCode[111] = 0354;
- deCode[112] = 0454;
- deCode[113] = 0554;
- deCode[114] = 0654;
- deCode[115] = 0754;
- deCode[116] = 0464;
- deCode[117] = 0564;
- deCode[118] = 0664;
- deCode[119] = 0764;
- deCode[120] = 0135;
- deCode[121] = 0235;
- deCode[122] = 0335;
- deCode[123] = 0435;
- deCode[124] = 0535;
- deCode[125] = 0245;
- deCode[126] = 0345;
- deCode[127] = 0445;
- deCode[128] = 0545;
- deCode[129] = 0645;
- deCode[130] = 0355;
- deCode[131] = 0455;
- deCode[132] = 0555;
- deCode[133] = 0655;
- deCode[134] = 0755;
- deCode[135] = 0065;
- deCode[136] = 0465;
- deCode[137] = 0565;
- deCode[138] = 0665;
- deCode[139] = 0765;
- deCode[140] = 0075;
- deCode[141] = 0175;
- deCode[142] = 0575;
- deCode[143] = 0675;
- deCode[144] = 0775;
- deCode[145] = 0006;
- deCode[146] = 0106;
- deCode[147] = 0606;
- deCode[148] = 0706;
- deCode[149] = 0346;
- deCode[150] = 0446;
- deCode[151] = 0546;
- deCode[152] = 0646;
- deCode[153] = 0356;
- deCode[154] = 0456;
- deCode[155] = 0556;
- deCode[156] = 0656;
- deCode[157] = 0756;
- deCode[158] = 0066;
- deCode[159] = 0466;
- deCode[160] = 0566;
- deCode[161] = 0666;
- deCode[162] = 0766;
- deCode[163] = 0076;
- deCode[164] = 0176;
- deCode[165] = 0576;
- deCode[166] = 0676;
- deCode[167] = 0776;
- deCode[168] = 0007;
- deCode[169] = 0107;
- deCode[170] = 0207;
- deCode[171] = 0607;
- deCode[172] = 0707;
- deCode[173] = 0017;
- deCode[174] = 0117;
- deCode[175] = 0217;
- deCode[176] = 0317;
- deCode[177] = 0717;
- deCode[178] = 0357;
- deCode[179] = 0457;
- deCode[180] = 0557;
- deCode[181] = 0657;
- deCode[182] = 0757;
- deCode[183] = 0067;
- deCode[184] = 0467;
- deCode[185] = 0567;
- deCode[186] = 0667;
- deCode[187] = 0767;
- deCode[188] = 0077;
- deCode[189] = 0177;
- deCode[190] = 0577;
- deCode[191] = 0677;
- deCode[192] = 0777;
- deCode[193] = 00;
- deCode[194] = 00;
- deCode[195] = 01;
- deCode[196] = 02;
- deCode[197] = 03;
- deCode[198] = 04;
- deCode[199] = 05;
- deCode[200] = 06;
- deCode[201] = 07;
- deCode[202] = 00;
- deCode[203] = 010;
- deCode[204] = 020;
- deCode[205] = 060;
- deCode[206] = 070;
- deCode[207] = 001;
- deCode[208] = 011;
- deCode[209] = 021;
- deCode[210] = 031;
- deCode[211] = 071;
- deCode[212] = 002;
- deCode[213] = 012;
- deCode[214] = 022;
- deCode[215] = 032;
- deCode[216] = 042;
- deCode[217] = 013;
- deCode[218] = 023;
- deCode[219] = 033;
- deCode[220] = 043;
- deCode[221] = 053;
- deCode[222] = 024;
- deCode[223] = 034;
- deCode[224] = 044;
- deCode[225] = 054;
- deCode[226] = 064;
- deCode[227] = 035;
- deCode[228] = 045;
- deCode[229] = 055;
- deCode[230] = 065;
- deCode[231] = 075;
- deCode[232] = 006;
- deCode[233] = 046;
- deCode[234] = 056;
- deCode[235] = 066;
- deCode[236] = 076;
- deCode[237] = 007;
- deCode[238] = 017;
- deCode[239] = 057;
- deCode[240] = 067;
- deCode[241] = 077;
-
- return (0);
- }
-
-
-
- /* PCCDECODE: function reads PCC code from code storage, and writes
- * out decoded image
- * usage: pccdecode (image, nX, nY, countflag)
- * If countflag = 0, lines are decoded to value 255; if
- * countflag != 0, lines are decoded into values 1-255
- * so different lines have different values.
- *
- */
-
- pccdecode (image, nX, nY, countflag)
- unsigned char **image; /* image region to be decoded */
- register long nX, nY; /* image region size */
- int countflag; /* different numbers for lines? */
- {
- register int iByteCode, /* code storage incrementor */
- codeWord, /* code word contains up to 3 dirn.s */
- x, y; /* feature coordinates */
- struct branch1 *branch; /* stack of branches to be decoded */
- struct branch1 branchTop; /* first branch */
- long nBranch; /* no. of branches in stack */
- int xTrack, yTrack; /* decode tracking coord.s */
-
- int imgon = IMGON;
-
- /* initialize branches and zero image region */
- nBranch = 0;
- branch = &branchTop;
- branch->previous = branch;
-
- for (y = 0; y < nY; y++)
- for (x = 0; x < nX; x++)
- image[y][x] = 0;
-
- /* decode from storage region to original position on screen */
-
- for (iByteCode = 0; iByteCode < nByteCode;) {
- codeWord = (int) fcCode[iByteCode++];
-
- /* if it is a feature: find start location if break, push branches
- * if junction, pop branches if endpoint */
-
- if (codeWord >= MINFEATCODE) {
- if (countflag) {
- imgon++;
- if (imgon >= 255)
- imgon = 1;
- }
- switch (codeWord) {
- case BIFCODE:
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- break;
- case CROSSCODE:
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- break;
- case ENDCODE: /* pop branches */
- if (nBranch > 0) {
- nBranch--;
- branch = branch->previous;
- xTrack = branch->x;
- yTrack = branch->y;
- }
- break;
- case STARTCODE:
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- image[yTrack][xTrack] = imgon;
- break;
- case LINEBRCODE:
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- image[yTrack][xTrack] = imgon;
- break;
- case BIFBRCODE:
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
-
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- image[yTrack][xTrack] = imgon;
- break;
- case CROSSBRCODE:
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- image[yTrack][xTrack] = imgon;
- break;
- case LINECODE:
- break;
- case STOPCODE:
- return (0);
- default:
- break;
- }
- }
-
- /* if it is a direction segment, write at proper location */
- else
- pccdetrack (image, &xTrack, &yTrack, codeWord, nX, nY, imgon);
- }
-
- printf ("PCCDECODE: missing STOPCODE in PCC storage \n");
-
- return (0);
- }
-
-
-
- /* PCCDETRACK: function decodes codeword and tracks directions
- * writing back thin lines as original
- * usage: nDirns = pccdetrack (image, &x, &y, codeWord)
- *
- */
-
- #define DECODE(BITSHIFT) \
- dirn = ((deCode[codeWord] >> BITSHIFT) & 07) + 1; \
- nbrtoxy (dirn, *x, *y, (long *)x, (long *)y); \
- if (*x < 0 || *x >= nX){ \
- /* printf ("PCCDETRACK: out of bounds (%4d, %4d)\n", *x, *y); */ \
- *x = nX - 1; \
- } \
- if (*y < 0 || *y >= nY){ \
- /* printf ("PCCDETRACK: out of bounds (%4d, %4d)\n", *x, *y); */ \
- *y = nY - 1; \
- } \
- image[*y][*x] = (unsigned char) imgon
-
- pccdetrack (image, x, y, codeWord, nX, nY, imgon)
- long nX, nY; /* image region size */
- unsigned char **image; /* image array */
- int *x, *y; /* input/output line coordinates */
- register long codeWord; /* code word contains up to 3 directions */
- long imgon; /* image color */
- {
- register long dirn; /* direction of next segment */
-
- /* 3 direction segments per code word */
- if (MINCODE3 <= codeWord && MAXCODE3 >= codeWord) {
- DECODE (0);
- DECODE (3);
- DECODE (6);
- return (3);
- }
-
- /* 2 direction segments per code word */
- if (MINCODE2 <= codeWord && MAXCODE2 >= codeWord) {
- DECODE (0);
- DECODE (3);
- return (2);
- }
-
- /* 1 direction segment per code word */
- if (MINCODE1 <= codeWord && MAXCODE1 >= codeWord) {
- DECODE (0);
- return (1);
- }
-
- /* 0 direction segment per code word */
- if (codeWord == CODE0) {
- return (0);
- }
- }
-
-
- /* PCC2XY: function reads PCC code from code storage, and lists
- * features and chain codes
- * usage: pcc2xy (data, &nData)
- *
- */
-
- pcc2xy (data, nData)
- struct point *data; /* data curve */
- long *nData; /* no. coords. in data curve */
- {
- register int iByteCode, /* code storage incrementor */
- codeWord; /* code word contains up to 3 dirn.s */
- long maxBranch; /* maximum branching number */
- long maxEdges; /* total number of edges in graph */
-
- struct branch1 *branch; /* stack of branches to be decoded */
- struct branch1 branchTop; /* first branch */
- long nBranch; /* no. of branches in stack */
- int xTrack, yTrack; /* decode tracking coord.s */
-
- /* initialize branches */
- *nData = 0;
- maxBranch = 0;
- maxEdges = 0;
- nBranch = 0;
- branch = &branchTop;
- branch->previous = branch;
-
- /* decode from storage region to original position on screen */
- for (iByteCode = 0; iByteCode < nByteCode;) {
- codeWord = (int) fcCode[iByteCode++];
-
- /* if it is a feature: find start location if break, push branches
- * if junction, pop branches if endpoint */
-
- if (codeWord >= MINFEATCODE) {
- switch (codeWord) {
- case BIFCODE:
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- if (nBranch > maxBranch)
- maxBranch = nBranch;
- data[(*nData)++].x = -BIFCODE;
- maxEdges++;
- break;
- case CROSSCODE:
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- if (nBranch > maxBranch)
- maxBranch = nBranch;
- data[(*nData)++].x = -CROSSCODE;
- maxEdges++;
- break;
- case ENDCODE: /* pop branches */
- if (nBranch > 0) {
- nBranch--;
- branch = branch->previous;
- xTrack = branch->x;
- yTrack = branch->y;
- maxEdges++;
- }
- data[(*nData)++].x = -ENDCODE;
- break;
- case STARTCODE:
- data[(*nData)++].x = -STARTCODE;
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- data[(*nData)].x = xTrack;
- data[(*nData)++].y = yTrack;
- maxEdges++;
- break;
- case LINEBRCODE:
- data[(*nData)++].x = -LINEBRCODE;
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- if (nBranch > maxBranch)
- maxBranch = nBranch;
- data[(*nData)].x = xTrack;
- data[(*nData)++].y = yTrack;
- maxEdges++;
- break;
- case BIFBRCODE:
- data[(*nData)++].x = -BIFBRCODE;
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- if (nBranch > maxBranch)
- maxBranch = nBranch;
- data[*nData].x = xTrack;
- data[(*nData)++].y = yTrack;
- maxEdges++;
- break;
- case CROSSBRCODE:
- data[(*nData)++].x = -CROSSBRCODE;
- xTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- yTrack = (long) *(fcCode + iByteCode)
- | ((long) *(fcCode + iByteCode + 1) << 8);
- iByteCode += 2;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- pccbranch (&branch, xTrack, yTrack, 0);
- nBranch++;
- if (nBranch > maxBranch)
- maxBranch = nBranch;
- data[*nData].x = xTrack;
- data[(*nData)++].y = yTrack;
- maxEdges++;
- break;
- case LINECODE:
- break;
- case STOPCODE:
- return (0);
- default:
- break;
- }
- }
-
- /* if it is a direction segment, write at proper location */
- else {
- detrack (&xTrack, &yTrack, codeWord, data, nData);
- }
- }
-
- printf ("PCCDECODE: missing STOPCODE in PCC storage \n");
-
- return (0);
- }
-
-
-
- /* DETRACK: function decodes PCC codeword and tracks directions
- * writing output array of coords.
- * usage: nDirns = detrack (&x, &y, codeWord, data,
- * &nData)
- *
- */
-
- extern int deCode[NDECODE]; /* decode table */
-
- #define DECODE2(BITSHIFT) \
- dirn = ((deCode[codeWord] >> BITSHIFT) & 07) + 1; \
- nbrtoxy (dirn, *x, *y, (long *)x, (long *)y); \
- data[*nData].x = *x; \
- data[(*nData)++].y = *y;
-
- detrack (x, y, codeWord, data, nData)
- int *x, /* input/output line coordinates */
- *y;
-
- register int codeWord; /* code word contains up to 3 directions */
-
- struct point *data; /* data curve */
- long *nData; /* no. coords. in data curve */
-
- {
- register int dirn; /* direction of next segment */
-
- /* 3 direction segments per code word */
- if (MINCODE3 <= codeWord && MAXCODE3 >= codeWord) {
- DECODE2 (0);
- DECODE2 (3);
- DECODE2 (6);
- return (3);
- }
-
- /* 2 direction segments per code word */
- if (MINCODE2 <= codeWord && MAXCODE2 >= codeWord) {
- DECODE2 (0);
- DECODE2 (3);
- return (2);
- }
-
- /* 1 direction segment per code word */
- if (MINCODE1 <= codeWord && MAXCODE1 >= codeWord) {
- DECODE2 (0);
- return (1);
- }
-
- /* 0 direction segment per code word */
- if (codeWord == CODE0) {
- return (0);
- }
- }
-