[comp.windows.x] enhancement to xsetroot for reading sun raster images

mdb@silvlis.COM (Mark D. Baushke) (06/04/88)

After getting a copy of "The Poskanzer Bitmap Collection" and finding
the disk consumption to be more than I was willing to use (making it
available for both X11 and sunview users was another consideration), I
converted all of the bitmaps from xbm format to sun's run-length
encoded image format (using xbmtopbm | pbmtorast | /usr/lib/rasfilters/convert.2).

The entire bitmap collection only takes about 6.5MB in run-length
encoded images. 

I hacked on xsetroot to add a "-rast" option to read in these
run-length encoded images. (Mostly by borrowing some code from Jef's
pbm package.)

The function XCreateBitmapFromSunPixrectData is based on
XCreateBitmapFromData.

This method also loads the background much faster than the "-bitmap"
option.

So for those running on sun hardware...enjoy. (You will need to modify
the Makefile to add -lpixrect to LDFLAGS or /usr/lib/libpixrect.a to
LOCAL_LIBRARIES.) 

*** xsetroot.c.orig	Thu Feb 25 21:12:18 1988
--- xsetroot.c	Fri Jun  3 12:26:28 1988
***************
*** 6,11 ****
--- 6,14 ----
  #include <stdio.h>
  #include "X11/bitmaps/gray"
  
+ #ifdef sun
+ #include <pixrect/pixrect_hs.h>
+ #endif
  /*
   * xsetroot.c 	MIT Project Athena, X Window system root window 
   *		parameter setting utility.  This program will set 
***************
*** 13,18 ****
--- 16,23 ----
   *
   *  Author:	Mark Lillibridge, MIT Project Athena
   *		11-Jun-87
+  * Modified:	Mark Baushke <mdb@silvlis.com>, to add -rast option
+  *  	    	3-Jun-88 
   */
  
  char *index();
***************
*** 45,50 ****
--- 50,56 ----
      fprintf(stderr, "  -solid <color>\n");
      fprintf(stderr, "  -gray   or   -grey\n");
      fprintf(stderr, "  -bitmap <filename>\n");
+     fprintf(stderr, "  -rast <filename>\n");
      fprintf(stderr, "  -mod <x> <y>\n");
      exit(1);
      /*NOTREACHED*/
***************
*** 51,56 ****
--- 57,65 ----
  }
  
  Pixmap MakeModulaBitmap(), ReadBitmapFile();
+ #ifdef sun
+ Pixmap  ReadSunRasterFile(), XCreateBitmapFromSunPixrectData();
+ #endif /* sun */
  XColor NameToXColor();
  unsigned long NameToPixel();
  
***************
*** 69,74 ****
--- 78,84 ----
      Cursor cursor;
      int gray = 0;
      char *bitmap_file = NULL;
+     char *rast_file = NULL;
      int mod_x = 0;
      int mod_y = 0;
      register int i;
***************
*** 131,136 ****
--- 141,159 ----
  	    excl++;
  	    continue;
  	}
+ 	if (!strcmp("-rast", argv[i])) {
+ #ifdef sun
+ 	    if (++i>=argc) usage();
+ 	    rast_file = argv[i];
+ 	    excl++;
+ 	    continue;
+ #else
+ 	    fprintf(stderr, "%s: "-rast" option not implemented.\n",
+ 		    program_name);
+ 	    if (++i>=argc) usage();
+ 	    continue;
+ #endif /* sun */
+ 	}
  	if (!strcmp("-mod", argv[i])) {
  	    if (++i>=argc) usage();
  	    mod_x = atoi(argv[i]);
***************
*** 150,157 ****
--- 173,186 ----
  
      /* Check for multiple use of exclusive options */
      if (excl > 1) {
+ #ifdef sun
+ 	fprintf(stderr,
+ 		"%s: choose only one of {solid, gray, bitmap, rast, mod}\n",
+ 		program_name);
+ #else
  	fprintf(stderr, "%s: choose only one of {solid, gray, bitmap, mod}\n",
  		program_name);
+ #endif /* sun */
  	usage();
      }
  
***************
*** 196,201 ****
--- 225,238 ----
  	SetBackgroundToBitmap(bitmap, ww, hh);
      }
    
+ #ifdef sun
+     /* Handle -rast option */
+     if (rast_file) {
+     	bitmap = ReadSunRasterFile(rast_file, &ww, &hh);
+ 	SetBackgroundToBitmap(bitmap, ww, hh);
+     }
+ #endif /* sun */
+ 
      /* Handle set background to a modula pattern */
      if (mod_x) {
  	bitmap = MakeModulaBitmap(mod_x, mod_y);
***************
*** 435,437 ****
--- 472,607 ----
      exit(1);
      /*NOTREACHED*/
  }
+ 
+ #ifdef sun
+ char *malloc();
+ 
+ Pixmap ReadSunRasterFile(filename, width, height)
+     char *filename;
+     unsigned int *width, *height;
+ {
+     Pixmap bitmap;
+     int status;
+     int rows, cols, linebytes;
+     short *data;
+     FILE *file;
+     struct rasterfile header;
+     struct pixrect *pr, *pr_load_image();
+     int firsttime, value, i, data_length;
+     
+     file = fopen(filename, "r");
+     if (file == NULL) {
+ 	fprintf(stderr, "%s: can't open file: %s\n", program_name,
+ 		filename);
+ 	exit(1);
+     }
+ 
+     cols = rows = -1;
+ 
+     /* Get the raster file's header. */
+     if (pr_load_header(file, &header) != 0) {
+ 	fprintf(stderr, "%s: Unable to read in raster file header.\n",
+ 		filename);
+ 	exit(1);
+     }
+ 
+     /* can only handle monochrome bitmaps. */
+     if (header.ras_depth != 1) {
+ 	fprintf(stderr, "%s: Invalid depth.\n", filename);
+ 	exit(1);
+     }
+ 
+     cols = header.ras_width;
+     rows = header.ras_height;
+     if (cols <= 0) {
+ 	fprintf(stderr, "%s: Invalid width: %d.\n", filename, cols);
+ 	exit(1);
+     }
+     
+     if (rows <= 0) {
+ 	fprintf(stderr, "%s: Invalid height: %d.\n", filename, rows);
+ 	exit(1);
+     }
+ 
+     /* If there is a color map, skip over it. */
+     if (header.ras_maptype != RMT_NONE && header.ras_maplength != 0) {
+ 	if (pr_load_colormap(file, &header, NULL) != 0) {
+ 	    fprintf(stderr, "%s: Unable to skip colormap data.\n", filename);
+ 	    exit(1);
+ 	}
+     }
+ 
+     /* Now load the data.  The pixrect returned is a memory pixrect. */
+     if ((pr = pr_load_image(file, &header, NULL)) == NULL) {
+ 	fprintf(stderr,
+ 		"Unable to read in the image from the raster file: %s.\n",
+ 		filename);
+ 	exit(1);
+     }
+     fclose(file);
+ 
+     linebytes = ((struct mpr_data *)pr->pr_data)->md_linebytes;
+     data = ((struct mpr_data *)pr->pr_data)->md_image;
+ 
+     *width = cols;
+     *height = rows;
+     bitmap = XCreateBitmapFromSunPixrectData(dpy, root, (char *) data,
+ 					    *width, *height, linebytes);
+     if (!bitmap) {
+ 	fprintf(stderr, "%s: insufficient memory for bitmap: %s",
+ 		program_name, filename);
+ 	exit(1);
+     }
+     return(bitmap);
+ }
+ 
+ 
+ /*
+  * XCreateBitmapFromSunPixrectData: Routine to make a pixmap of depth 1 from user supplied data.
+  *             D is any drawable on the same screen that the pixmap will be used in.
+  *             Data is a pointer to the bit data, and 
+  *             width & height give the size in bits of the pixmap.
+  *
+  * The following format is assumed for data:
+  *
+  *    format=XYPixmap
+  *    bit_order=MSBFirst
+  *    byte_order=MSBFirst
+  *    padding=8
+  *    bitmap_unit=8
+  *    xoffset=0
+  *    rows are rounded up to 16-bit boundaries
+  */  
+ Pixmap XCreateBitmapFromSunPixrectData(display, d, data, width,
+ 				       height, linebytes)
+      Display *display;
+      Drawable d;
+      char *data;
+      unsigned int width, height;
+      int linebytes;
+ {
+     XImage ximage;
+     GC gc;
+     Pixmap pix;
+ 
+     pix = XCreatePixmap(display, d, width, height, 1);
+     if (!pix)
+       return(0);
+     gc = XCreateGC(display, pix, (unsigned long)0, (XGCValues *)0);
+     ximage.height = height;
+     ximage.width = width;
+     ximage.depth = 1;
+     ximage.xoffset = 0;
+     ximage.format = XYPixmap;
+     ximage.data = data;
+     ximage.byte_order = MSBFirst;
+     ximage.bitmap_unit = 8;
+     ximage.bitmap_bit_order = MSBFirst;
+     ximage.bitmap_pad = 8;
+     ximage.bytes_per_line = (linebytes == 0) ? (((width+15)>>3) & ~1) : linebytes; 
+     
+     XPutImage(display, pix, gc, &ximage, 0, 0, 0, 0, width, height);
+     XFreeGC(display, gc);
+     return(pix);
+ }
+ #endif /* sun */

------------------------------------------------------------------------------
Mark D. Baushke                 Internet:    mdb%silvlis.com@sun.com
Silvar-Lisco, Inc.              Nameservers: mdb@silvlis.com
1080 Marsh Road                 Usenet:      {pyramid,sun}!silvlis!mdb
Menlo Park, CA 94025-1053       Telephone:   +1 415 853-6411 / +1 415 969-8328