[comp.windows.news] shared memory canvas animation: mapper.shar

don@CS.UMD.EDU (Don Hopkins) (05/30/90)

This is a program that uses a shared memory canvas in the X11/NeWS
server to quickly animate a sequence of raster images on the screen.
The input file should contain a sequence of raw 8 bit images, no
headers, no colormaps, just the the uncompressed pixel values.  It
read the images from the input file into shared memory, and tells the
NeWS server to "imagecanvas" each frame on the screen, then waits for
it to finish, plus a specified delay, before reading and displaying
the next frame. I don't know how it'll deal with the strange
framebuffer colormap situation in OpenWindows 2.0. It should work
slowly in monochrome because "imagecanvas" has to dither the images,
but it should be easy to modify it to animate 1 bit deep images.

	-Don

--- DELETE EVERYTHING ABOVE & INCLUDING THIS LINE, AND RUN THROUGH SH ---
: Run this shell script with "sh" not "csh"
PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH
export PATH
all=false
if [ x$1 = x-a ]; then
	all=true
fi
echo Extracting Makefile
sed 's/^X//' <<'//go.sysin dd *' >Makefile
XCFLAGS = -O4
X#CFLAGS = -g
XNEWSHOME = /usr/NeWS
XLIBCPS = ${NEWSHOME}/lib/libcps.a
X
Xmapper: mapper.o
X	cc ${CFLAGS} mapper.o ${LIBCPS} -o mapper
X
Xmapper.o: mapper.c mapper.h
X	cc ${CFLAGS} -I${NEWSHOME}/include -c mapper.c
X
Xmapper.h: mapper.cps
X	cps mapper.cps
X
Xclean:
X	rm -f mapper mapper.o mapper.h *.BAK *~ core
//go.sysin dd *
if [ `wc -c < Makefile` != 311 ]; then
	made=false
	echo error transmitting Makefile --
	echo length should be 311, not `wc -c < Makefile`
else
	made=true
fi
if $made; then
	chmod 644 Makefile
	echo -n '	'; ls -ld Makefile
fi
echo Extracting mapper.c
sed 's/^X//' <<'//go.sysin dd *' >mapper.c
X/*
X * mapper.c
X * Copyright (C) 1990 by Don Hopkins
X *
X * SunOS 4.0 memory mapping client for X11/NeWS
X *
X * mapper InputFile SharedFile Width Height USleep SkipBytes
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <sys/mman.h>
X#include <sys/vadvise.h>
X#include <stdio.h>
X#include "mapper.h"
X
Xchar *InputFile;
Xchar *SharedFile;
Xint X, Y, Width, Height;
Xint USleep;
Xint SkipBytes;
Xint ImageBytes;
Xint RowBytes;
Xint Input;
Xchar *Image;
Xchar *Padding;
X
Xchar *mmap_sharedfile();
Xint unmap_sharedfile();
X
Xmain (argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X  if (argc != 9) {
X    fprintf(stderr,
X      "usage: mapper InputFile SharedFile X Y Width Height USleep SkipBytes\n");
X    exit(1);
X  }
X
X  InputFile = argv[1];
X  SharedFile = argv[2];
X  X = atoi(argv[3]);
X  Y = atoi(argv[4]);
X  Width = atoi(argv[5]);
X  Height = atoi(argv[6]);
X  USleep = atoi(argv[7]);
X  SkipBytes = atoi(argv[8]);
X
X  ImageBytes = Width * Height;
X
X  if (strcmp(InputFile, "-") == 0) {
X    Input = fileno(stdin);
X  } else if ((Input = open(InputFile, O_RDONLY, 0)) < 0) {
X    fprintf(stderr, "Can't open input file %s\n", InputFile);
X    exit(1);
X  }
X
X  ps_open_PostScript();
X  ps_initialize(SharedFile, Width, Height, &RowBytes);
X
X  if ((Image = mmap_sharedfile(SharedFile, ImageBytes)) == (char *)-1) {
X    fprintf(stderr, "Can't mmap %d byte file %\n", ImageBytes, SharedFile);
X  }
X
X  Padding = (char *)malloc(SkipBytes);
X
X  pump();
X}
X
X/*
X * mmap_sharedfile - mmap the given absolute filename for memlen number
X * of bytes rounded to page boundary.  File will be mapped R/W.
X * Caller should check for validity of returned pointer.
X */
X
Xchar *
Xmmap_sharedfile(absfn, memlen)
X  char *absfn;
X  int memlen;
X{
X  struct stat statbuf;
X  char *buf;
X  register int wtemp, fd;
X  register int pagesize;
X  static char ar[] = {0x0};
X
X  pagesize = getpagesize();
X  memlen = pagesize * ((memlen + pagesize - 1) / pagesize);
X
X  if (!(fd = open(absfn, O_RDWR, 0666)))
X    return((char *)-1);
X  /* check out the filesize, extend if needed */
X  if (stat(absfn, &statbuf))
X    return((char *)-1);
X  if (statbuf.st_size < memlen) {
X    wtemp = lseek(fd, (off_t)(memlen-1), L_SET);
X    if (wtemp == -1) {
X      close(fd);
X      return((char *)-1);
X    }
X    if (write(fd, ar, 1) != 1) {
X      close(fd);
X      return((char *)-1);
X    }
X  }
X
X  /* Map the file pages */
X  buf = (char *)mmap((caddr_t)0, memlen, PROT_READ|PROT_WRITE,
X		     MAP_SHARED, fd, (off_t)0);
X  close(fd);
X  return(buf);
X}
X
X
X/*
X * unmap_sharedfile - munmap the given pointer for memlen number of
X * bytes rounded to page boundary.  Caller should check for return
X * value.
X */
X
Xint
Xunmap_sharedfile(buf, memlen)
X  caddr_t buf;
X  int memlen;
X{
X  register int pagesize;
X
X  pagesize = getpagesize();
X  memlen = pagesize * ((memlen + pagesize - 1) / pagesize);
X
X  if (msync(buf, memlen, MS_INVALIDATE) < 0)
X    return(-1);
X  if (munmap(buf, memlen) < 0)
X    return(-1);
X
X  return(0);
X}
X
Xpump()
X{
X  char *p;
X  int syncin, syncout;
X  int n;
X  int dontseek = 0;
X
X  vadvise(VA_SEQL);
X
X  while (1) {
X    if (!dontseek &&
X        (lseek(Input, (off_t)SkipBytes, L_INCR) < 0)) {
X      fprintf(stderr, "Seek failed -- trying to read instead!\n");
X      dontseek = 1;
X    }
X    if (dontseek &&
X        ((n = read(Input, Padding, SkipBytes)) != SkipBytes)) {
X      fprintf(stderr, "Read %d/%d skip bytes -- exiting!\n", n, SkipBytes);
X      break;
X    }
X
X    if ((n = read(Input, Image, ImageBytes)) == ImageBytes) {
X      ps_splat(X, Y);
X      ps_sync(syncin,&syncout);
X      syncin++;
X      usleep(USleep);
X    } else {
X      fprintf(stderr, "Read %d/%d image bytes -- exiting!\n", n, ImageBytes);
X      break;
X    }
X  }
X}
//go.sysin dd *
if [ `wc -c < mapper.c` != 3671 ]; then
	made=false
	echo error transmitting mapper.c --
	echo length should be 3671, not `wc -c < mapper.c`
else
	made=true
fi
if $made; then
	chmod 644 mapper.c
	echo -n '	'; ls -ld mapper.c
fi
echo Extracting mapper.cps
sed 's/^X//' <<'//go.sysin dd *' >mapper.cps
XC: #define ROWBYTES_TAG 1
XC: #define SYNC_TAG 2
X#define ROWBYTES_TAG 1
X#define SYNC_TAG 2
X
Xcdef ps_initialize(string SharedFile, Width, Height, LineBytes)
X  => ROWBYTES_TAG(LineBytes)
X
X  /height Height def
X  /width Width def
X  /sharedfile SharedFile def
X  /canvas
X    width height 8 [width 0 0 height neg 0 height] null buildimage
X  def
X  canvas /RowBytes get ROWBYTES_TAG tagprint typedprint
X  canvas /SharedFile sharedfile put
X
Xcdef ps_splat(x, y)
X  gsave
X    framebuffer setcanvas
X    x y translate
X    width height scale
X    canvas imagecanvas
X  grestore
X
Xcdef ps_sync(In, Out) => SYNC_TAG(Out)
X  SYNC_TAG tagprint In typedprint
//go.sysin dd *
if [ `wc -c < mapper.cps` != 634 ]; then
	made=false
	echo error transmitting mapper.cps --
	echo length should be 634, not `wc -c < mapper.cps`
else
	made=true
fi
if $made; then
	chmod 644 mapper.cps
	echo -n '	'; ls -ld mapper.cps
fi