/*---------------------------------------------------------------------- Grey level include file J. R. Parker Laboratory for Computer Vision University of Calgary Calgary, Alberta, Canada ---------------------------------------------------------------------- */ #include <stdio.h> #include <math.h> #include <malloc.h> #include <fcntl.h> #include <stdlib.h> /* #include "dos.h" */ /* #include "bios.h" */ /* #include "graphics.h" */ /* #include "io.h" */ /* The image header data structure */ struct header { int nr, nc; /* Rows and columns in the image */ int oi, oj; /* Origin */ }; /* The IMAGE data structure */ struct image { struct header *info; /* Pointer to header */ unsigned char **data; /* Pixel values */ }; #define SQRT2 1.414213562 #define BLACK 0 #define WHITE 1 long seed = 132531; typedef struct image * IMAGE; #if defined (MAX) int PBM_SE_ORIGIN_COL=0, PBM_SE_ORIGIN_ROW=0; char **arg; int maxargs; #else extern int PBM_SE_ORIGIN_COL, PBM_SE_ORIGIN_ROW; #endif int range (IMAGE im, int i, int j); void print_se (IMAGE p); IMAGE Input_PBM (char *fn); IMAGE Output_PBM (IMAGE image, char *filename); void get_num_pbm (FILE *f, char *b, int *bi, int *res); void pbm_getln (FILE *f, char *b); void pbm_param (char *s); struct image *newimage (int nr, int nc); void freeimage (struct image *z); void sys_abort (int val, char *mess); void CopyVarImage (IMAGE *a, IMAGE *b); void Display (IMAGE x); float ** f2d (int nr, int nc); void srand32 (long k); double drand32 (); void disp_lo_grey (struct image *x); void disp_hi_grey (struct image *x); /* Check that a pixel index is in range. Return TRUE(1) if so. */ int range (IMAGE im, int i, int j) { if ((i<0) || (i>=im->info->nr)) return 0; if ((j<0) || (j>=im->info->nc)) return 0; return 1; } /* PRINT_SE - Print a structuring element to the screen */ void print_se (IMAGE p) { int i,j; printf ("\n=====================================================\n"); if (p == NULL) printf (" Structuring element is NULL.\n"); else { printf ("Structuring element: %dx%d origin at (%d,%d)\n", p->info->nr, p->info->nc, p->info->oi, p->info->oj); for (i=0; i<p->info->nr; i++) { printf (" "); for (j=0; j<p->info->nc; j++) printf ("%4d ", p->data[i][j]); printf ("\n"); } } printf ("\n=====================================================\n"); } IMAGE Input_PBM (char *fn) { int i,j,k,n,m,bi, b; unsigned char ucval; int val; long here; char buf1[256]; FILE *f; IMAGE im; strcpy (buf1, fn); f = fopen (buf1, "r"); if (f==NULL) { printf ("Can't open the PBM file named '%s'\n", buf1); return 0; } pbm_getln (f, buf1); if (buf1[0] == 'P') { switch (buf1[1]) { case '1': k=1; break; case '2': k=2; break; case '3': k=3; break; case '4': k=4; break; case '5': k=5; break; case '6': k=6; break; default: printf ("Not a PBM/PGM/PPM file.\n"); return 0; } } bi = 2; get_num_pbm (f, buf1, &bi, &m); /* Number of columns */ get_num_pbm (f, buf1, &bi, &n); /* Number of rows */ if (k!=1 && k!=4) get_num_pbm (f, buf1, &bi, &b); /* Max value */ else b = 1; fprintf (stderr,"\nPBM file class %d size %d columns X %d rows Max=%d\n", k, m, n, b); /* Binary file? Re-open as 'rb' */ if (k>3) { here = ftell (f); fclose (f); f = fopen (fn, "rb"); here++; if (fseek(f, here, 0) != 0) { printf ("Input_PBM: Sync error, file '%s'. Use ASCII PGM.\n",fn); exit (3); } } /* Allocate the image */ if (k==3 || k==6) /* Colour */ sys_abort (0, "Colour image."); else { im = (IMAGE)newimage (n, m); im->info->oi = PBM_SE_ORIGIN_ROW; im->info->oj = PBM_SE_ORIGIN_COL; PBM_SE_ORIGIN_ROW = 0; PBM_SE_ORIGIN_COL = 0; for (i=0; i<n; i++) for (j=0; j<m; j++) if (k<3) { fscanf (f, "%d", &val); im->data[i][j] = (unsigned char)val; } else { fscanf (f, "%c", &ucval); im->data[i][j] = ucval; } } return im; } IMAGE Output_PBM (IMAGE image, char *filename) { FILE *f; int i,j,k, perline; char buf1[64]; strcpy (buf1, filename); if (image->info->nc > 20) perline = 20; else perline = image->info->nc-1; f = fopen (buf1, "w"); if (f == 0) sys_abort (0, "Can't open output file."); fprintf (f,"P2\n#origin %d %d\n",image->info->oj,image->info->oi); fprintf (f, "%d %d %d\n", image->info->nc, image->info->nr, 255); k = 0; for (i=0; i<image->info->nr; i++) for (j=0; j<image->info->nc; j++) { fprintf (f, "%d ", image->data[i][j]); k++; if (k > perline) { fprintf (f, "\n"); k = 0; } } fprintf (f, "\n"); fclose (f); return image; } void get_num_pbm (FILE *f, char *b, int *bi, int *res) { int i; char str[80]; while (b[*bi]==' ' || b[*bi]=='\t' || b[*bi]=='\n') { if (b[*bi] == '\n') { pbm_getln (f, b); *bi = 0; } else *bi += 1; } i = 0; while (b[*bi]>='0' && b[*bi]<='9') str[i++] = b[(*bi)++]; str[i] = '\0'; sscanf (str, "%d", res); } /* Get the next non-comment line from the PBM file f into the buffer b. Look for 'pragmas' - commands hidden in the comments */ void pbm_getln (FILE *f, char *b) { int i; char c; /* Read the next significant line (non-comment) from f into buffer b */ do { /* Read the next line */ i = 0; do { fscanf (f, "%c", &c); b[i++] = c; if (c == '\n') b[i] = '\0'; } while (c != '\n'); /* If a comment, look for a special parameter */ if (b[0] == '#') pbm_param (b); } while (b[0]=='\n' || b[0] == '#'); } /* Look for a parameter hidden in a comment */ void pbm_param (char *s) { int i,j; char key[24]; /* Extract the key word */ for (i=0; i<23; i++) { j = i; if (s[i+1] == ' ' || s[i+1] == '\n') break; key[i] = s[i+1]; } key[j] = '\0'; /* Convert to lower case */ for (i=0; i<j; i++) if ( (key[i]>='A') && (key[i]<='Z') ) key[i] = (char) ( (int)key[i] - (int)'A' + (int)'a' ); /* Which key word is it? */ if (strcmp(key, "origin") == 0) /* ORIGIN key word */ { sscanf (&(s[j+1]), "%d %d", &PBM_SE_ORIGIN_COL, &PBM_SE_ORIGIN_ROW); return; } } struct image *newimage (int nr, int nc) { struct image *x; /* New image */ unsigned char *ptr; /* new pixel array */ int i; if (nr < 0 || nc < 0) { printf ("Error: Bad image size (%d,%d)\n", nr, nc); return 0; } /* Allocate the image structure */ x = (struct image *) malloc( sizeof (struct image) ); if (!x) { printf ("Out of storage in NEWIMAGE.\n"); return 0; } /* Allocate and initialize the header */ x->info = (struct header *)malloc( sizeof(struct header) ); if (!(x->info)) { printf ("Out of storage in NEWIMAGE.\n"); return 0; } x->info->nr = nr; x->info->nc = nc; x->info->oi = x->info->oj = 0; /* Allocate the pixel array */ x->data = (unsigned char **)malloc(sizeof(unsigned char *)*nr); /* Pointers to rows */ if (!(x->data)) { printf ("Out of storage in NEWIMAGE.\n"); return 0; } for (i=0; i<nr; i++) { x->data[i] = (unsigned char *)malloc(nc*sizeof(unsigned char)); if (x->data[i]==0) { printf ("Out of storage. Newimage - row %d\n", i); exit(1); } } return x; } void freeimage (struct image *z) { /* Free the storage associated with the image Z */ int i; if (z != 0) { for (i=0; i<z->info->nr; i++) free (z->data[i]); free (z->info); free (z->data); free (z); } } void sys_abort (int val, char *mess) { fprintf (stderr, "**** System library ABORT %d: %s ****\n", val, mess); exit (2); } void copy (IMAGE *a, IMAGE b) { CopyVarImage (a, &b); } void CopyVarImage (IMAGE *a, IMAGE *b) { int i,j; if (a == b) return; if (*a) freeimage (*a); *a = newimage ((*b)->info->nr, (*b)->info->nc); if (*a == 0) sys_abort (0, "No more storage.\n"); for (i=0; i<(*b)->info->nr; i++) for (j=0; j< (*b)->info->nc; j++) (*a)->data[i][j] = (*b)->data[i][j]; (*a)->info->oi = (*b)->info->oi; (*a)->info->oj = (*b)->info->oj; } void Display (IMAGE x) { Output_PBM (x, "x.tmp"); system ("disp x.tmp"); system ("del x.tmp"); /* if (x->info->nr <= 200 && x->info->nc <= 320) disp_lo_grey (x); else disp_hi_grey (x); */ } float ** f2d (int nr, int nc) { float **x, *y; int i; x = (float **)calloc ( nr, sizeof (float *) ); if (x == 0) { fprintf (stderr, "Out of storage: F2D.\n"); exit (1); } for (i=0; i<nr; i++) { x[i] = (float *) calloc ( nc, sizeof (float) ); if (x[i] == 0) { fprintf (stderr, "Out of storage: F2D %d.\n", i); exit (1); } } return x; } /* Small system random number generator */ double drand32 () { static long a=16807L, m=2147483647L, q=127773L, r = 2836L; long lo, hi, test; hi = seed / q; lo = seed % q; test = a*lo -r*hi; if (test>0) seed = test; else seed = test + m; return (double)seed/(double)m; } void srand32 (long k) { seed = k; } /* Display the image X using grey color map in 320x200 resolution */ /* void disp_lo_grey (IMAGE x) */ /* { */ /* int i, j, map[256], r, g, b; */ /* FILE *f; */ /* */ /* f = fopen ("debug", "w"); */ /* */ /* Initialize the graphics system */ /* GrSetMode (GR_default_graphics); */ /* */ /* Set all colors in the palette to greys */ /* for (i=0; i<256; i++) */ /* { */ /* map[i] = GrAllocColor (i, 0, 55); */ /* GrQueryColor (i, &r, &g, &b); */ /* fprintf (f, "Colour %d is [%d, %d, %d]\n", i, r, g, b); */ /* } */ /* Copy pixels to the VGA */ /* for(i=0; i<x->info->nr; i++) */ /* { */ /* for (j=0; j<x->info->nc; j++) */ /* { */ /* GrPlot3d (j, i, map[(int)(x->data[i][j])] ); */ /* fprintf (f, "%3d ", GrPixel (j, i)); */ /* if (j%14==0) fprintf (f, "\n"); */ /* } */ /* fprintf (f, "\n"); */ /* } */ /* fclose (f); */ /* */ /* Stop displaying when the user pushes the 'enter' key */ /* bioskey (0); */ /* GrSetMode (GR_default_text); */ /*} */ /* Display the image X as grey levels, 640x480 pixels */ /*void disp_hi_grey (struct image *x) */ /*{ */ /* int i,j, nr, nc; */ /* */ /* Initialize the graphics system */ /* GrSetMode (GR_default_graphics); */ /* for (i=0; i<256; i++) */ /* GrSetColor (i, i, i, i); */ /* */ /* nr = x->info->nr; nc = x->info->nc; */ /* if (nr > 480) nr = 480; */ /* if (nc > 640) nc = 640; */ /* */ /* Send the pixels to the VGA */ /* for(i=0; i<nr; i++) */ /* for (j=0; j<nc; j++) */ /* GrPlot (j, i, (int)x->data[i][j]); */ /* */ /* bioskey(0); */ /* GrSetMode(GR_default_text); */ /*} */