jim@athsys.uucp (Jim Becker) (09/01/88)
Please excuse the following source posting to comp.windows.x, but my stuff isn't complex enough for comp.sources.x to accept it.. The following is new bitmap reading code that is considerably faster than the R2 release. It has been submitted for R3. It replaces the XRdBitF.c file in the "core.src/lib/X" directory on the distribution, for building the library libX11.a. You only need it if you read a lot of bitmaps from disk. -Jim Becker --skip or snip-- /* Copyright, 1987, Massachusetts Institute of Technology */ #include "copyright.h" /* * Code to read bitmaps from disk files. Interprets * data from X10 and X11 bitmap files and creates * Pixmap representations of files. Returns Pixmap * ID and specifics about image. * * Modified for speedup by Jim Becker, changed image * data parsing logic (removed some fscanf()s). * Aug 5, 1988 */ #include <ctype.h> #include <stdio.h> #include <sys/types.h> #include <X11/Xos.h> #include "Xlib.h" #include "Xutil.h" #include "Xlibint.h" #define MAX_SIZE 255 /* shared data for the image read/parse logic */ static FILE *fstream; /* file read handle */ static short HexVal[255]; /* conversion value */ static short HexSet = 0; /* initialized flag */ /* * Table index for the hex values. Initialized once, first time. * Used for translation value or delimiter significance lookup. */ static SetupHex() { /* set the translation entry values that are meaningful */ HexVal['0'] = 0; HexVal['1'] = 1; HexVal['2'] = 2; HexVal['3'] = 3; HexVal['4'] = 4; HexVal['5'] = 5; HexVal['6'] = 6; HexVal['7'] = 7; HexVal['8'] = 8; HexVal['9'] = 9; HexVal['A'] = 10; HexVal['B'] = 11; HexVal['C'] = 12; HexVal['D'] = 13; HexVal['E'] = 14; HexVal['F'] = 15; HexVal['a'] = 10; HexVal['b'] = 11; HexVal['c'] = 12; HexVal['d'] = 13; HexVal['e'] = 14; HexVal['f'] = 15; /* delimiters of significance are flagged w/ negative value */ HexVal[' '] = -1; HexVal[','] = -1; HexVal['}'] = -1; HexVal['\n'] = -1; HexVal['\t'] = -1; HexSet++; } /* * read next hex value in the input stream, return -1 if EOF */ static NextInt() { int ch; int value = 0; short gotone = 0; short done = 0; /* loop, accumulate hex value until find delimiter */ /* skip any initial delimiters found in read stream */ while( !done ) { ch = getc(fstream); if( ch == EOF ) { value = -1; done++; } else { /* trim high bits, check type and accumulate */ if( isxdigit( (ch &= 0xff) ) ) { value = (value << 4) + HexVal[ch]; gotone++; } else if( (HexVal[ch]) < 0 && gotone ) done++; } } return value; } int XReadBitmapFile( display, d, filename, width, height, pixmap, x_hot, y_hot ) Display *display; Drawable d; char *filename; unsigned int *width, *height; /* RETURNED */ Pixmap *pixmap; /* RETURNED */ int *x_hot, *y_hot; /* RETURNED */ { char *data = NULL; char *ptr; char line[MAX_SIZE]; int size, bytes; char name_and_type[MAX_SIZE]; char *type; int value; int version10p; int padding; int bytes_per_line; Pixmap pix; unsigned int ww = 0; unsigned int hh = 0; int hx = -1; int hy = -1; /* error cleanup and return macro */ #define RETURN(code) {if(data) free(data); \ fclose(fstream);\ return(code);} /* first time initialization */ if( !HexSet ) SetupHex(); if (!(fstream = fopen(filename, "r"))) return(BitmapOpenFailed); while(fgets(line, MAX_SIZE, fstream)) { if (strlen(line) == MAX_SIZE-1) RETURN(BitmapFileInvalid); if (sscanf(line, "#define %s %d", name_and_type, &value) == 2) { if (!(type = rindex(name_and_type, '_'))) type = name_and_type; else type++; if (!strcmp("width", type)) ww=(unsigned int) value; if (!strcmp("height", type)) hh=(unsigned int) value; if (!strcmp("hot", type)) { if (type--==name_and_type || type--==name_and_type) continue; if (!strcmp("x_hot", type)) hx = value; if (!strcmp("y_hot", type)) hy = value; } continue; } if (sscanf(line, "static short %s = {", name_and_type) == 1) version10p = 1; else if (sscanf(line, "static unsigned char %s = {", name_and_type) == 1) version10p = 0; else if (sscanf(line, "static char %s = {", name_and_type) == 1) version10p = 0; else continue; if (!(type = rindex(name_and_type, '_'))) type = name_and_type; else type++; if (strcmp("bits[]", type)) continue; if (!ww || !hh) RETURN(BitmapFileInvalid); if ((ww % 16) && ((ww % 16) < 9) && version10p) padding = 1; else padding = 0; bytes_per_line = (ww+7)/8 + padding; size = bytes_per_line * hh; data = (char *)Xmalloc( size ); if (!data) RETURN(BitmapNoMemory); if (version10p) for (bytes=0, ptr=data; bytes<size; (bytes += 2)) { if ( (value = NextInt()) < 0 ) RETURN(BitmapFileInvalid); *(ptr++) = value; if (!padding || ((bytes+2) % bytes_per_line)) *(ptr++) = value >> 8; } else for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) { if ( (value = NextInt()) < 0 ) RETURN(BitmapFileInvalid); *ptr=value; } } if( data == NULL ) RETURN(BitmapFileInvalid); /* take data and convert to a pixmap for the user */ pix = XCreateBitmapFromData(display, d, data, ww, hh); if( pix == NULL ) RETURN(BitmapNoMemory); *pixmap = pix; *width = ww; *height = hh; if( x_hot != NULL ) *x_hot = hx; if( y_hot != NULL ) *y_hot = hy; RETURN(BitmapSuccess); }
jkh@violet.berkeley.edu (Jordan K. Hubbard) (09/02/88)
In article <129@tityus.UUCP> jim@athsys.uucp (Jim Becker) writes: > >Please excuse the following source posting to comp.windows.x, but >my stuff isn't complex enough for comp.sources.x to accept it.. > >The following is new bitmap reading code that is considerably >faster than the R2 release. It has been submitted for R3. It Great. Do the plans for R3 also provide a routine for getting just the bits from a bitmap image, so that one can then convert it into a pixmap of arbitraty depth and color(s)? Jordan
jim@athsys.uucp (Jim Becker) (09/03/88)
From article <13842@agate.BERKELEY.EDU>, by jkh@violet.berkeley.edu (Jordan K. Hubbard): > In article <129@tityus.UUCP> jim@athsys.uucp (Jim Becker) writes: > > Great. Do the plans for R3 also provide a routine for getting just the bits > from a bitmap image, so that one can then convert it into a pixmap > of arbitraty depth and color(s)? > Jordan This is the primary reason that I had to originally get into this code, as it builds you a pixmap rather than letting you get to the bits. (This was a change that was put in with the X10->X11 changes.) By cloning this routine, renaming it and modifying the logic not to create the pixmap from the data you can get what you want. If you return the "data" pointer instead of a pixmap XID you can then get at the bits. Also, there was a minor bug to this that causes it not to be reentrant. The "fstream" variable should be local to the XReadBitmapFile routine, and passed to the routine NextInt. Otherwise there could be problems. Otherwise, it seems fine. Email me if this is not clear, as I want to keep net clutter down. -Jim Becker