/* * bitmaps.c - varios bitmap utilities (b&w images) * * $Log: bitmaps.c,v $ * Revision 1.13 1994/06/01 22:25:52 clm * fixed memcpy calls so images are displayed correctly * * Revision 1.12 1994/05/04 23:34:36 clm * ported to ANSI C * * Revision 1.11 1992/09/11 15:50:49 clm * copied Kevin's version with IMAGE_DIRECTORY to xopps * * Revision 1.5 1991/09/12 03:57:45 kevin * added IMAGE_DIRECTORY * * Revision 1.4 1991/07/09 17:07:14 chester * added function headers * * Revision 1.3 1991/05/31 21:55:13 chester * replace free and malloc with X toolkit XtFree and XtMalloc. * added void typecasts to standard C functions. * added return statement to scale bitmap. * * Revision 1.2 1991/03/14 19:25:14 chester * no change... just a mistake. * * Revision 1.1 1991/01/17 16:57:34 chester * Initial revision * * * Derived from xgened bitmaps.c 1.4 */ #include #include #include #include #include #include #include "xopps.h" #ifndef lint static char rcsid[] = "$Id: bitmaps.c,v 1.13 1994/06/01 22:25:52 clm OEL $"; #endif #define get_pixel(data, rowlen, x, y) (*((data) + (y) * (rowlen) + (x) / 8) \ & (1 << ((x) % 8))) #define set_pixel(data, rowlen, x, y) *((data) + (y) * (rowlen) + (x) / 8) \ |= (1 << ((x) % 8)) /* local function declarations */ static GRBitmap *read_X11_bitmap(FILE *); /*********************************************************************** * * FUNCTION: * open_bitmap() * * INPUTS: * filename - (char*) name of bitmap file * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * reads various format b&w bitmaps from file * */ GRBitmap * open_bitmap(char *filename) { FILE *fp; /* file pointer */ GRBitmap *bm; /* return image */ char newpath[1024]; /* full pathname with IMAGE_DIRECTORY */ char *tp; /* value of IMAGE_DIRECTORY */ if ((filename != NULL) && (filename[0] != '\0')) { if ((fp = fopen(filename, "r")) == NULL) { if (filename[0] != '/') { tp = getenv("IMAGE_DIRECTORY"); if (tp != NULL) { strcpy(newpath, tp); strcat(newpath, "/"); strcat(newpath, filename); } fp = fopen(newpath, "r"); } } } else { fp = NULL; } if (fp != NULL) { bm = read_X11_bitmap(fp); (void)fclose(fp); } else { bm = NULL; } return bm; } /*********************************************************************** * * FUNCTION: * read_X11_bitmap() * * INPUTS: * fp - (FILE *) file pointer to the bitmap file * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * reads X11 bitmap data file * */ static GRBitmap * read_X11_bitmap(FILE *fp) { GRBitmap *bm; /* returned bitmap */ char buf[128], *ptr; /* input buffer */ int width, height; /* size of image */ unsigned long length; /* length of bitmap in bytes */ bm = (GRBitmap *)XtMalloc(sizeof(GRBitmap)); bm->bits = NULL; /* look for #define *_width */ while (1) { if (fgets(buf, 128, fp) == NULL) goto bad_file; if (strncmp(buf, "#define", 7)) continue; if ((ptr = strstr(buf + 7, "_width")) == NULL) continue; width = atoi(ptr + 6); if ((width <= 0) || (width > 65535)) goto bad_file; bm->width = (unsigned short)width; break; } /* look for #define *_height */ while (1) { if (fgets(buf, 128, fp) == NULL) goto bad_file; if (strncmp(buf, "#define", 7)) continue; if ((ptr = strstr(buf + 7, "_height")) == NULL) continue; height = atoi(ptr + 7); if ((height <= 0) || (height > 65535)) goto bad_file; bm->height = (unsigned short)height; break; } /* skip over header */ while (1) { if (fgets(buf, 128, fp) == NULL) goto bad_file; if (strncmp(buf, "static char", 11)) continue; if (strstr(buf + 11, "_bits[] = {") == NULL) continue; break; } /* calculate length of bitmap in bytes and allocate memory */ length = height * ((width - 1) / 8 + 1); ptr = bm->bits = XtMalloc(length); /* read in bitmap */ while (length--) { if (fscanf(fp, "%s", buf) != 1) goto bad_file; if (buf[0] != '0') goto bad_file; if (buf[1] != 'x') goto bad_file; if (!isxdigit(buf[2])) goto bad_file; if (!isxdigit(buf[3])) goto bad_file; if ((length) && (buf[4] != ',')) goto bad_file; *ptr = (buf[2] - (isupper(buf[2]) ? ('A' - 10) : (islower(buf[2]) ? ('a' - 10) : '0'))) << 4; *ptr |= (buf[3] - (isupper(buf[3]) ? ('A' - 10) : (islower(buf[3]) ? ('a' - 10) : '0'))); ++ptr; } /* everything was ok */ return bm; /* remove bitmap structure and quit on error */ bad_file: if (bm->bits != NULL) XtFree(bm->bits); XtFree((char *)bm); return NULL; } /*********************************************************************** * * FUNCTION: * copy_bitmap() * * INPUTS: * bm1 - (GRBitmap *) Pointer to Bitmap structure * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * */ GRBitmap * copy_bitmap(GRBitmap *bm1) { GRBitmap *bm2; Cardinal length; if (bm1 == NULL) { bm2 = NULL; } else { bm2 = (GRBitmap *)XtMalloc(sizeof(GRBitmap)); bm2->width = bm1->width; bm2->height = bm1->height; length = bm1->height * ((bm1->width - 1) / 8 + 1); bm2->bits = (char *)XtMalloc(length); memcpy(bm2->bits, bm1->bits, length); } return bm2; } /*********************************************************************** * * FUNCTION: * scale_bitmap() * * INPUTS: * bm1 - (GRBitmap *) pointer to the gr_routine bitmap structure * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * */ GRBitmap * scale_bitmap(GRBitmap *bm1, int scale) { GRBitmap *bm2; /* reduced bitmap */ Cardinal length; /* length of reduced bitmap */ int rowlen1, rowlen2; /* row length of each bitmap */ int x, y, i, j, x1, y1; /* coordinates */ int count; /* count of pixels turned on */ int total; /* total number of pixels in this sub-area */ int threshold; /* threshold for turning new pixel on */ int area; /* area of old bitmap */ if (bm1 == NULL) { bm2 = NULL; } else if (scale == 1) { bm2 = (GRBitmap *)XtMalloc(sizeof(GRBitmap)); bm2->width = bm1->width; bm2->height = bm1->height; length = bm1->height * ((bm1->width - 1) / 8 + 1); bm2->bits = (char *)XtMalloc(length); memcpy(bm2->bits, bm1->bits, length); } else { bm2 = (GRBitmap *)XtMalloc(sizeof(GRBitmap)); bm2->width = (bm1->width - 1) / scale + 1; bm2->height = (bm1->height - 1) / scale + 1; length = bm2->height * ((bm2->width - 1) / 8 + 1); bm2->bits = (char *)XtMalloc(length); memset(bm2->bits, '\0', length); rowlen1 = (bm1->width - 1) / 8 + 1; rowlen2 = (bm2->width - 1) / 8 + 1; threshold = 0; /* find threshold */ for (x = 0; x < bm1->width; x++) { for (y = 0; y < bm1->height; y++) { if (get_pixel(bm1->bits, rowlen1, x, y)) threshold++; } } area = bm1->width * bm1->height; for (x = 0; x < bm2->width; x++) { /* calculate new points */ for (y = 0; y < bm2->height; y++) { count = 0; total = 0; for (i = 0; i < scale; i++) { x1 = scale * x + i; if (x1 < bm1->width) { for (j = 0; j < scale; j++) { y1 = scale * y + j; if (y1 < bm1->height) { ++total; if (get_pixel(bm1->bits, rowlen1, x1, y1)) count++; } } } } if (count * area > threshold * total) set_pixel(bm2->bits, rowlen2, x, y); } } } return bm2; }