david@ics.COM (David B. Lewis) (10/18/89)
Several months ago someone posted information on the development of a standard for writing X pixmaps to files. As I recall, it had been named PAX but was quickly renamed. Does anyone know what has become of this effort? Does anyone have the address of the people reponsible? Thanks in advance. -- David B. Lewis david@ics.com ics!david@buita.bu.edu david%ics.UUCP@buita.bu.edu "No, I'm a member of the X User's Group, not the Ex-User's Group."
colas@trinidad.inria.fr (Colas Nahaboo) (10/19/89)
In article <3381@ics.COM>, david@ics.COM (David B. Lewis) writes: > Several months ago someone posted information on the development of > a standard for writing X pixmaps to files. As I recall, it had been named > PAX but was quickly renamed. We have renamed it XPM (X PixMap), and we call our bitmaps XBM (X BitMaps) > Does anyone know what has become of this effort? It is used by GWM and by the font editor xfedor (made by Daniel Dardailler of the Koala team -- BULL Research). The C routines work but are not optimized (slow), and only support 2 ascii chars for a color. > Does anyone have the address of the people reponsible? Daniel DARDAILLER Colas NAHABOO BULL Research FRANCE -- Koala Project (GWM X11 Window Manager) Internet: daniel@mirsa.inria.fr, colas@mirsa.inria.fr Surface Mail: INRIA - Sophia Antipolis, 2004, route des Lucioles, 06565 Valbonne Cedex -- FRANCE Voice phone: (33) 93.65.77.71, Fax: (33) 93 65 77 66, Telex: 97 00 50 F And, if anybody else is interested, here is the code of the C routines patterned along the Xlib ones for bitmaps. Take them, and may the source be with you! Feed the rest of this mail to /bin/sh: #/bin/sh cat > xpm.h << \END_OF_SHAR_FOR_xpm.h /* Copyright 1989 GROUPE BULL -- See licence conditions in file COPYRIGHT */ /************************************************************************** **** Constant used in xpm library functions : **** **** int XWritePixmapFile(dpy, cmap, filename, pixmap, w, h) **** int XReadPixmapFile(dpy, d, cmap, filename, w, h, depth, pixmap) **** Pixmap XCreatePixmapFromData(dpy, d, cmap, w, h, depth, n, c, col, pix) **** **** Daniel Dardailler - Bull RC (89/02/22) e-mail: daniel@mirsa.inria.fr **************************************************************************/ #define XPM_FORMAT 1 /* we keep the same codes as for Bitmap management */ #ifndef _XUTIL_H_ #include <X11/Xutil.h> #endif #define PixmapSuccess BitmapSuccess #define PixmapOpenFailed BitmapOpenFailed #define PixmapFileInvalid BitmapFileInvalid #define PixmapNoMemory BitmapNoMemory typedef struct _Cixel { char c1,c2 ; } Cixel ; /* 2 chars for one pixel value */ typedef struct _CmapEntry { Cixel cixel ; int red,green,blue ; } CmapEntry ; #define MAXPRINTABLE 93 /* number of printable ascii chars minus \ and " for string compat. */ static char * printable = " .XoO+@#$%&*=-;:?>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZASDFGHJKLPIU YTREWQ!~^/()_`'][{}|" ; /* printable begin with a space, so in most case, due to my algorythm, when the number of different colors is less than MAXPRINTABLE, it will give a char follow by "nothing" (a space) in the readable xpm file */ END_OF_SHAR_FOR_xpm.h cat > xpm.c << \END_OF_SHAR_FOR_xpm.c /* Copyright 1989 GROUPE BULL -- See licence conditions in file COPYRIGHT */ /************************************************************************** **** Read/Write package for XPM file format (X PixMap) **** **** int XWritePixmapFile(dpy, cmap, filename, pixmap, w, h) **** int XReadPixmapFile(dpy, d, cmap, filename, w, h, depth, pixmap) **** Pixmap XCreatePixmapFromData(dpy, d, cmap, w, h, depth, n, c, col, pix) **** **** Daniel Dardailler - Bull RC (89/02/22) e-mail: daniel@mirsa.inria.fr **************************************************************************/ /*************************************************************************** **** Look of XPM file : .. something like X11 'C includable' format #define drunk_format 1 #define drunk_width 18 #define drunk_height 21 #define drunk_ncolors 4 #define drunk_chars_per_pixel 2 static char * drunk_colors[] = { " " , "#FFFFFFFFFFFF", ". " , "#A800A800A800", "X " , "White", "o " , "#540054005400" } ; static char * drunk_pixels[] = { " ", " ", " . . . . . . . ", " X . . . . ", " X X . . . . ", " o X . . . ", " o o X . . . . ", " o o o . . . . . ", "o o o . . . . . . ", "o o o . . . . ", " X X . . . ", " X X . . . . ", " X . . . . ", " X . . ", " X X X X ", " X X X X X ", " X X X ", " X X X X X ", " X X X X ", " X X ", " " } ; ************************************************************************* * Version 1 can handle a variable number of chars per pixel * - for each different color : n chars can represent the pixel value * and is associed with red, green and blue intensity or colorname. **************************************************************************/ /*************************************************************************/ #include <stdio.h> #include <X11/Xlib.h> #include "xpm.h" /* PixmapOpenFailed, PixmapSuccess .. MAXPRINTABLE */ /*----------------------------------------------------------------------*/ /* * Write a X Color Pixmap through a specified colormap * (THIS VERSION PRODUCE ONLY 2 CHARS PER PIXEL FORMAT : '_chars_per_pixel 2') */ int XWritePixmapFile(display, colormap, filename, pixmap, width, height) /*------------------*/ Display * display; Colormap colormap ; char *filename; Pixmap pixmap; unsigned int width, height; { XImage *image; /* client image */ FILE *stream; char *name, *stripname; int ncolors = 0 ; /* number of different colors */ CmapEntry * cmap ; /* indexed by ncolors, dynamicaly allocated by width */ Cixel * Map ; /* should be [width][height] */ int i,j,p ; XColor * colors ; int MaxCixel ; /* theorytical max */ if (!filename) return(PixmapOpenFailed); stripname = (char *) malloc(strlen(filename)); if (stripname == NULL) return PixmapNoMemory ; strcpy(stripname,filename); /* no more use of filename */ /* extract the short name of the pixmap */ if (!(name = (char *)rindex(stripname, '/'))) name = stripname; else name++; if (!(stream = fopen(stripname, "w"))) return(PixmapOpenFailed); if (stripname = (char *)index(name, '.')) *stripname = '\0' ; /* modify both name and stripname */ /* Convert pixmap to an image in client memory */ image = XGetImage(display, pixmap, 0,0,width, height, AllPlanes, ZPixmap); /* calcul of ncolors, cmap, Map in a while */ colors = (XColor *) malloc(width*sizeof(XColor)); cmap = (CmapEntry *) malloc(MAXPRINTABLE*sizeof(CmapEntry)); Map = (Cixel *) malloc(sizeof(Cixel)*width*height); if ((colors == NULL) || (cmap == NULL) || (Map == NULL)) return PixmapNoMemory ; MaxCixel = (MAXPRINTABLE*MAXPRINTABLE)-1 ; for (j=0 ; j<height ; j++) { for (i=0; i<width ; i++) colors[i].pixel = XGetPixel(image,i,j) ; /* ask server for rgb values line by line */ XQueryColors(display,colormap,colors,width); /* return : colors */ for (i=0; i<width ; i++) { for (p=0; p<ncolors; p++) if ((colors[i].red == cmap[p].red) && (colors[i].green == cmap[p].green) && (colors[i].blue == cmap[p].blue)) { /* already present */ *(Map + j*width + i) = cmap[p].cixel ; break ; /* stop with p < ncolors */ } if (p == ncolors) { /* new rgb value in cmap */ cmap[ncolors].red = colors[i].red ; cmap[ncolors].green = colors[i].green ; cmap[ncolors].blue = colors[i].blue ; cmap[ncolors].cixel.c1 = printable[ncolors % MAXPRINTABLE]; cmap[ncolors].cixel.c2 = printable[ncolors / MAXPRINTABLE]; *(Map + j*width + i) = cmap[ncolors].cixel ; if (ncolors < MaxCixel) ncolors++ ; if (ncolors % MAXPRINTABLE) /* => much memory for cmap */ cmap = (CmapEntry *) realloc((char*)cmap, (ncolors+MAXPRINTABLE)*sizeof(CmapEntry)); if (cmap == NULL) return PixmapNoMemory ; } } } /* Write out standard header */ fprintf(stream, "#define %s_format %d\n",name,XPM_FORMAT); fprintf(stream, "#define %s_width %d\n",name,width); fprintf(stream, "#define %s_height %d\n",name,height); fprintf(stream, "#define %s_ncolors %d\n",name,ncolors); fprintf(stream, "#define %s_chars_per_pixel %d\n",name,2); fprintf(stream, "static char * %s_colors[] = {\n",name); for (i=0; i<ncolors ; i++) { fprintf(stream, "\"%c%c\" , \"#%X%X%X\"", cmap[i].cixel.c1,cmap[i].cixel.c2, cmap[i].red,cmap[i].green,cmap[i].blue); if (i != (ncolors - 1)) fprintf(stream,",\n"); else fprintf(stream,"\n"); } fprintf(stream, "} ;\n"); fprintf(stream, "static char * %s_pixels[] = {\n",name); for (j=0; j<height ; j++) { fprintf(stream, "\""); for (i=0; i<width ; i++) fprintf(stream, "%c%c", (*(Map + j*width + i)).c1, (*(Map + j*width + i)).c2); if (j != (height - 1)) fprintf(stream,"\",\n"); else fprintf(stream,"\"\n"); } fprintf(stream, "} ;\n"); free(colors); free(cmap); free(Map) ; XDestroyImage(image); fclose(stream); return PixmapSuccess ; } /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /* following routines are used in XReadPixmapFile() function */ /*------------------------------------------------------------*/ /* * read the next line and jump blank lines */ static char * getline(s,pF) char * s ; FILE * pF ; { s = fgets(s,256,pF); while (s) { int len = strlen(s); if (len && s[len-1] == '\015') s[--len] = '\0'; if (len==0) s = fgets(s,256,pF); else break; } return(s); } /* * fatal message : return code, no exit */ static int fatal(msg, p1, p2, p3, p4) char *msg; { fprintf(stderr,"\n"); fprintf(stderr, msg, p1, p2, p3, p4); fprintf(stderr,"\n"); return PixmapFileInvalid ; } /* * Read a Pixmap file in a X Pixmap with specified depth and colormap * (THIS VERSION READ ONLY 2 CHARS PER PIXEL FORMAT : '_chars_per_pixel 2') */ int XReadPixmapFile (display,d,colormap,filename,width,height,depth,pixmap) /*-----------------*/ Display *display; Drawable d; Colormap colormap ; char *filename; unsigned int *width, *height; /* RETURNED */ int depth ; Pixmap *pixmap; /* RETURNED */ { GC Gc ; XGCValues xgcv; FILE *fstream; /* handle on file */ char linebuf[256] ; char namebuf[256]; char type[256]; char name[256]; int ncolors ; CmapEntry * cmap ; int * Tpixel ; char c1, c2, c; int red, green, blue ; XColor xcolor ; int i,j,p; if ((fstream = fopen(filename, "r")) == NULL) { return PixmapOpenFailed; } getline(linebuf,fstream); if ((sscanf(linebuf, "#define %[^_]%s %d", namebuf, type, &p) != 3) || ((strcmp("_format",type)) && (strcmp("_paxformat",type))) || (p != XPM_FORMAT)) return fatal("bad '#define NAME_format 1'"); else strcpy(name,namebuf); getline(linebuf,fstream); if ((sscanf(linebuf, "#define %[^_]%s %d", namebuf, type, width) != 3) || (strcmp(name,namebuf)) || (strcmp("_width",type))) return fatal("bad '#define NAME_width w'"); getline(linebuf,fstream); if ((sscanf(linebuf, "#define %[^_]%s %d", namebuf, type, height) != 3) || (strcmp(name,namebuf)) || (strcmp("_height",type))) return fatal("bad '#define NAME_height w'"); getline(linebuf,fstream); if ((sscanf(linebuf, "#define %[^_]%s %d", namebuf, type, &ncolors) != 3) || (strcmp(name,namebuf)) || (strcmp("_ncolors",type))) return fatal("bad '#define NAME_ncolors w'"); if (ncolors > (MAXPRINTABLE*MAXPRINTABLE)) return fatal("Too many different colors, version 1"); getline(linebuf,fstream); if ((sscanf(linebuf, "#define %[^_]%s %d", namebuf, type, &p) != 3) || (strcmp(name,namebuf)) || (p != 2) || (strcmp("_chars_per_pixel",type))) return fatal("bad '#define NAME_chars_per_pixel 2'"); getline(linebuf,fstream); if ((sscanf(linebuf, "static char * %[^_]%s = {",namebuf,type) != 2) || (strcmp(name,namebuf)) || (strcmp("_colors[]",type))) return fatal("bad 'static char * NAME_colors[] = {'"); cmap = (CmapEntry *) malloc(ncolors*sizeof(CmapEntry)) ; Tpixel = (int *) malloc(ncolors*sizeof(int)) ; if ((cmap == NULL) || (Tpixel == NULL)) return PixmapNoMemory ; getline(linebuf,fstream); for (i=0; i<ncolors ; i++) { if (sscanf(linebuf, "\"%c%c\" , \"%[^\"]%s", &c1,&c2, namebuf,type) != 4) return fatal("bad colormap entry : must be '\"cC\" , \"colordef\",'"); if ((index(printable,c1)) && (index(printable,c2))) { cmap[i].cixel.c1 = c1 ; cmap[i].cixel.c2 = c2 ; if (!XParseColor(display,colormap,namebuf,&xcolor)) return fatal("bad colordef specification : #RGB or colorname"); XAllocColor(display,colormap,&xcolor); Tpixel[i] = xcolor.pixel ; } else return fatal("bad cixel value : must be printable"); getline(linebuf,fstream); } if (strncmp(linebuf, "} ;",3)) return fatal("missing '} ;'"); getline(linebuf,fstream); if ((sscanf(linebuf, "static char * %[^_]%s = {",namebuf,type) != 2) || (strcmp(name,namebuf)) || (strcmp("_pixels[]",type))) return fatal("bad 'static char * NAME_pixels[] = {'"); *pixmap = XCreatePixmap(display,d,*width,*height,depth); Gc = XCreateGC(display,*pixmap,0,&xgcv); getline(linebuf,fstream); j = 0 ; while((j < *height) && strncmp(linebuf, "} ;",3)) { if (strlen(linebuf) < (2*(*width)+2)) return fatal("bad pixmap line length %d",strlen(linebuf)); for (i=1; i<(2*(*width)) ; i+=2) { c1 = linebuf[i] ; c2 = linebuf[i+1] ; for (p = 0 ; p < ncolors ; p++) if ((cmap[p].cixel.c1 == c1)&&(cmap[p].cixel.c2 == c2)) break ; if (p != ncolors) XSetForeground(display,Gc,Tpixel[p]); else return fatal("cixel %c%c not in previous colormap",c1,c2); XDrawPoint(display,*pixmap,Gc,i/2,j) ; } j++ ; getline(linebuf,fstream); } if (strncmp(linebuf, "} ;",3)) return fatal("missing '} ;'"); if (j != *height) return fatal("%d too few pixmap line", *height - j); free(cmap) ; free(Tpixel) ; fclose(fstream) ; return PixmapSuccess ; } /* * This function allows you to include in your C program (using #include) * a pixmap file in XPM format that was written by XWritePixmapFile * (THIS VERSION MANAGE ONLY 2 CHARS PER PIXEL FORMAT : '_chars_per_pixel 2') */ Pixmap XCreatePixmapFromData(display, d, colormap, width, height, depth, ncolors, chars_per_pixel, colors, pixels) /*-------------------------*/ Display *display; Drawable d; Colormap colormap ; unsigned int width, height; int depth ; unsigned int ncolors ; unsigned int chars_per_pixel ; char ** colors ; /* array of colormap entries "cc","#RRGGBB" */ char ** pixels ; /* array of pixels lines "cc..cc00cccc.." */ { Pixmap pixmap ; GC Gc ; XGCValues xgcv; CmapEntry * cmap ; int * Tpixel ; char c1, c2, c; int red, green, blue ; XColor xcolor ; int i,j,p; if (ncolors > (MAXPRINTABLE*MAXPRINTABLE)) return fatal("Too many different colors, version 1"); if (chars_per_pixel != 2) return fatal("version 1 handle only 2 chars_per_pixel"); /* now we construct cmap and Tpixel from colors array parameter */ cmap = (CmapEntry *) malloc(ncolors*sizeof(CmapEntry)) ; Tpixel = (int *) malloc(ncolors*sizeof(int)) ; if ((cmap == NULL) || (Tpixel == NULL)) return PixmapNoMemory ; if (!colors) return fatal("colors not defined"); for (i=0; i<2*ncolors ; i+=2) { if (sscanf(colors[i],"%c%c", &c1,&c2) != 2) return fatal("bad colormap entry : must be '\"cC\" , \"colordef\",'"); if ((index(printable,c1)) && (index(printable,c2))) { cmap[i/2].cixel.c1 = c1 ; cmap[i/2].cixel.c2 = c2 ; if (!XParseColor(display,colormap,colors[i+1],&xcolor)) return fatal("bad colordef specification : #RGB or colorname"); XAllocColor(display,colormap,&xcolor); Tpixel[i] = xcolor.pixel ; } else return fatal("bad cixel value : must be printable"); } pixmap = XCreatePixmap(display,d,width,height,depth); Gc = XCreateGC(display,pixmap,0,&xgcv); if (!pixels) return fatal("pixels not defined"); j = 0 ; while (j < height) { if (strlen(pixels[j]) != (2*width)) return fatal("bad pixmap line length %d",strlen(pixels[j])); for (i=0; i< (2*width) ; i+=2) { c1 = pixels[j][i] ; c2 = pixels[j][i+1] ; for (p = 0 ; p < ncolors ; p++) if ((cmap[p].cixel.c1 == c1)&&(cmap[p].cixel.c2 == c2)) break ; if (p != ncolors) XSetForeground(display,Gc,Tpixel[p]); else return fatal("cixel %c%c not in previous colormap",c1,c2); XDrawPoint(display,pixmap,Gc,i/2,j) ; } j++ ; } free(cmap) ; free(Tpixel) ; return pixmap ; } END_OF_SHAR_FOR_xpm.c
david@ics.COM (David B. Lewis) (10/19/89)
In article <3381@ics.COM>, david@ics.COM (David B. Lewis) writes: > Several months ago someone posted information on the development of > a standard for writing X pixmaps to files. As I recall, it had been named > PAX but was quickly renamed. > > Does anyone know what has become of this effort? > Does anyone have the address of the people reponsible? Daniel Dardailler of the BULL Centre de Sophia Antipolis has forwarded details of his XPM text-based pixmap-description scheme to me. -- David B. Lewis david@ics.com ics!david@buita.bu.edu david%ics.UUCP@buita.bu.edu Some financial models, on the other hand, yield a positive societal value for a pack of cigarettes: smokers ... inflate group life-insurance premiums, but they tend to die before costing society much in pensions or nursing-home care. - SA