Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

v23i010: rndbg - nice random background on your screen, Part01/01

4 views
Skip to first unread message

Niclas Wiberg

unread,
Mar 14, 1995, 10:09:14 PM3/14/95
to
Submitted-by: ni...@isy.liu.se (Niclas Wiberg)
Posting-number: Volume 23, Issue 10
Archive-name: rndbg/part01
Environment: X11, background

"rndbg" creates a random black and white image and installs it as
background. The image is designed to be "neutral but not lifeless". It
consists of a rectangle that is replicated to fill up the whole screen.

The size of the rectangle can be changed using command line arguments.
As an option, the image can be written on standard output (in XBM format)
instead of installed as the root image.

The program has only been tested on Sun sparc running SunOS 4.1.1, but
probably it should work on other Unixes with little or no problems.
It is however written in ANSI C, so on a Sun you need to have gcc.

Niclas Wiberg, October 1994
Linkoping University, Sweden
ni...@isy.liu.se

#!/bin/sh
# This is a shell archive (produced by GNU shar 4.0).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1994-10-13 16:55 MET by <nicwi@niblick>.
# Source directory was `/tmp_mnt/home/it2/nicwi/src/rndbg'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1339 -rw-r--r-- README
# 1470 -rw-r--r-- rndbg.man
# 7194 -rw-r--r-- rndbg.c
# 133 -rw-r--r-- Imakefile
# 205 -rw-r--r-- Makefile.std
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo 'WARNING: not restoring timestamps'
fi
rm -f 1231235999 $$.touch
#
# ============= README ==============
if test -f 'README' && test X"$1" != X"-c"; then
echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
rndbg - nice random background on your screen
X
DESCRIPTION
X "rndbg" creates a random black and white image and installs it as
X background. The image is designed to be "neutral but not lifeless". It
X consists of a rectangle that is replicated to fill up the whole screen.
X
X The size of the rectangle can be changed using command line arguments.
X As an option, the image can be written on standard output (in XBM format)
X instead of installed as the root image.
X
ALGORITHM
X The algorithm for generating the random image is quite simple. Start
X with an empty (black) image. Then place white pixels on random positions
X such that no two adjacent pixels are white (each pixel has four adjacent
X pixels; borders are treated in a "wrap-around" fashion). This process is
X repeated until no more white pixels can be placed.
X
X The result is quite fascinating. You have to see it!
X
INSTALLATION
X The program has only been tested on Sun sparc running SunOS 4.1.1, but
X probably it should work on other Unixes with little or no problems.
X It is however written in ANSI C, so on a Sun you need to have gcc.
X
X To compile it, either check and fix Makefile.std and type
X make -f Makefile.std
X or go for the Imakefile and type
X xmkmf
X make
X
AUTHOR
X Niclas Wiberg, October 1994
X Linkoping University, Sweden
X ni...@isy.liu.se
SHAR_EOF
$shar_touch -am 1013165594 'README' &&
chmod 0644 'README' ||
echo 'restore of README failed'
shar_count="`wc -c < 'README'`"
test 1339 -eq "$shar_count" ||
echo "README: original size 1339, current size $shar_count"
fi
# ============= rndbg.man ==============
if test -f 'rndbg.man' && test X"$1" != X"-c"; then
echo 'x - skipping rndbg.man (File already exists)'
else
echo 'x - extracting rndbg.man (text)'
sed 's/^X//' << 'SHAR_EOF' > 'rndbg.man' &&
X.TH RNDBG 1 "October 1994" "ISY Linkoping"
X.SH NAME
rndbg \- random background on X11 display
X.SH SYNOPSIS
X.B rndbg
[
X.B -xbm
X.I name
|
X.B -display
X.I display
]
[
X.I width
[
X.I height
]
]
X.SH DESCRIPTION
X.B rndbg
creates a random black and white image and installs it as
background. The image is designed to be "neutral but not lifeless".
It consists of a rectangular bitmap that is replicated to fill up the
whole screen. The size of the rectangle can be changed using command line
arguments.
X.PP
As an option, the image can be written on standard output (in XBM format)
instead of installed as background.
X.SH OPTIONS
X.TP
X.BI -xbm " name"
Write image in XBM format on standard input, instead of installing it
as background. The parameter
X.I name
specifies the name used in the bitmap file.
X.TP
X.BI -display " display"
The display on which to install the background. By default, the
display name is taken from the environment variable DISPLAY.
X.TP
X.I width
The width in pixels of the replicated rectangle. The default value is 256.
X.TP
X.I height
The height in pixels of the replicated rectangle. By default, the height
is the same as the width (256).
X.SH EXAMPLES
X.LP
To install a random background of the default size:
X.RS
X.B example% rndbg
X.RE
X.PP
To create a random bitmap of size 20x30 named "background":
X.RS
X.B example% rndbg -xbm background 20 30 >background.xbm
X.RE
X.SH "SEE ALSO"
XX(1), xsetroot(1)
X.SH AUTHOR
Niclas Wiberg, Linkoping University, October 1994
SHAR_EOF
$shar_touch -am 1013163294 'rndbg.man' &&
chmod 0644 'rndbg.man' ||
echo 'restore of rndbg.man failed'
shar_count="`wc -c < 'rndbg.man'`"
test 1470 -eq "$shar_count" ||
echo "rndbg.man: original size 1470, current size $shar_count"
fi
# ============= rndbg.c ==============
if test -f 'rndbg.c' && test X"$1" != X"-c"; then
echo 'x - skipping rndbg.c (File already exists)'
else
echo 'x - extracting rndbg.c (text)'
sed 's/^X//' << 'SHAR_EOF' > 'rndbg.c' &&
/* rndbg.c - random background on X11 display
X
X "rndbg" creates a random black and white image and installs it as
X background. The image is designed to be "neutral but not lifeless".
X It consists of a rectangle that is replicated to fill up the whole screen.
X
X The size of the rectangle can be changed using command line arguments.
X As an option, the image can be written on standard output (in XBM format)
X instead of installed as the root image.
X
X The program has only been tested on Sun sparc running SunOS 4.1.1.
X
X The algorithm for generating the random image is quite simple.
X Start with an empty (black) image. Then place white pixels on random
X positions such that no two adjacent pixels are white (each pixel has
X four adjacent pixels; borders are treated in a "wrap-around" fashion).
X This process is repeated until no more white pixels can be placed.
X
X The result is quite fascinating. You have to see it!
X
X Niclas Wiberg, October 1994
X Linkoping University, Sweden
X ni...@isy.liu.se
*/
X
#include <stdio.h>
#include <malloc.h>
#include <X11/Xlib.h>
#include <math.h> /* We use floor() to select random pixel */
#include <time.h> /* We use time() to get random number seed */
extern void srand48(long seed); /* Initialize random number generator */
extern double drand48(); /* Return random in [0..1[ */
X
/*
X * Global parameters
X */
char *progname;
char *xbmname = NULL;
int width = 256;
int height = 256;
char *display = NULL;
X
/*
X * The result image in bitmap format
X */
char *bitmap = NULL;
X
/*
X * Forward declarations
X */
void args(int argc, char **argv);
void usage();
void rndbm();
void install_picture();
void output_xbm();
X
X
int main(int argc, char **argv)
{
X progname = argv[0];
X args(argc, argv);
X rndbm();
X if (xbmname) output_xbm();
X else install_picture();
X return 0;
}
X
void usage()
{
X fprintf(stderr,
X "usage: %s [-xbm <name> | -display <display>] [width [height]]\n",
X progname);
X exit(1);
}
X
void args(int argc, char **argv)
{
X int i;
X if (argc == 1) return;
X if (! strcmp(argv[1], "-xbm")) {
X if (argc < 3) usage();
X xbmname = argv[2];
X i = 3;
X } else if (! strcmp(argv[1], "-display")) {
X if (argc < 3) usage();
X display = argv[2];
X i = 3;
X } else i = 1;
X if (i < argc) if (! sscanf(argv[i++], "%u", &width)) usage();
X height = width;
X if (i < argc) if (! sscanf(argv[i++], "%u", &height)) usage();
X if (i < argc) usage();
}
X
/*
X * install_picture()
X *
X * Install the result image as background pixmap on root window.
X */
void install_picture()
{
X Display *dpy;
X int screen;
X Window root;
X Pixmap pxm;
X
X dpy = XOpenDisplay(display);
X if (! dpy) {
X fprintf(stderr, "%s: can't open display %s\n", progname, display);
X exit(1);
X }
X screen = DefaultScreen(dpy);
X root = RootWindow(dpy, screen);
X pxm = XCreatePixmapFromBitmapData(dpy, root, bitmap, width, height,
X BlackPixel(dpy, screen),
X WhitePixel(dpy, screen),
X DefaultDepth(dpy, screen));
X XSetWindowBackgroundPixmap(dpy, root, pxm);
X XFreePixmap(dpy, pxm);
X XClearWindow(dpy, root);
X XCloseDisplay(dpy);
}
X
/*
X * output_xbm()
X *
X * Write out the resulting bitmap in xbm format on standard output.
X */
void output_xbm()
{
X int i, n;
X printf("#define %s_width %d\n", xbmname, width);
X printf("#define %s_height %d\n", xbmname, height);
X printf("static char %s_bits[] = {\n", xbmname);
X n = (width + 7) / 8 * height;
X for (i = 0; i < n; i++) {
X if (i % 12 == 0) printf(" ");
X printf("0x%02x", bitmap[i] & 0xff);
X if (i == n - 1) printf("};\n");
X else if (i % 12 == 11) printf(",\n");
X else printf(", ");
X }
}
X
X
/*
X * The algorithm
X *
X * Although the algorithm is simple in theory, we have to make it
X * slightly more complicated to make it fast. The problem is to quickly
X * select random pixels that are "free", i.e., that do not have any
X * white neighbors. We do this by maintaining two data strucures:
X * A 2d-array for the pixels (pix), and a list pointing to the free
X * pixels (freepix). Pixels whose color has not yet been determined
X * point back to their positions in the freepix array.
X */
X
typedef struct {
X short x, y;
} coord;
X
/* pix[x][y] is either BLACK, WHITE or an index into freepix */
#define BLACK -1
#define WHITE -2
int **pix;
X
/* freepix[i], for i=0..remain-1, points to the free pixels in pix */
int remain;
coord *freepix;
X
/*
X * init()
X *
X * Allocate memory.
X * Initialize the freepix list, with back pointers from pix[x][y].
X */
void init()
{
X int x, y, i, j, k;
X
X pix = (int **) malloc(width * sizeof(int *));
X if (! pix) {perror(progname); exit(1);}
X for (x = 0; x < width; x++) {
X pix[x] = (int *) malloc(height * sizeof(int));
X if (! pix[x]) {perror(progname); exit(1);}
X }
X
X freepix = (coord *) malloc(width * height * sizeof(coord));
X if (! freepix) {perror(progname); exit(1);}
X
X bitmap = (char *) malloc((width + 7) / 8 * height * sizeof(char));
X if (! bitmap) {perror(progname); exit(1);}
X
X /* Initialize the freepix list, with back pointers from pix[x][y] */
X k = 0;
X for (x = 0; x < width; x++) {
X for (y = 0; y < height; y++) {
X pix[x][y] = k;
X freepix[k].x = x;
X freepix[k].y = y;
X k++;
X }
X }
X remain = height * width;
}
X
/*
X * set(int x, int y, int value)
X *
X * Assign a value (BLACK or WHITE) to a pixel.
X * If the pixel was free before, we have to remove it from the freepix list.
X * In this case, we may have to reorder the list, since we want the free
X * pixels to be indexed as 0..remain-1.
X */
void set(int x, int y, int value)
{
X int this; /* Index in freepix */
X
X /* Ensure that we are inside rectangle (wrap-around at borders) */
X while (x < 0) x += width;
X while (x >= width) x -= width;
X while (y < 0) y += height;
X while (y >= height) y -= height;
X
X /* Skip rest if pixel was set before (not free) */
X if (pix[x][y] < 0) return;
X
X /* Get this pixel's index in freepix list */
X this = pix[x][y];
X
X /* If this pixel was not last in the freepix list, we replace it with
X the last pixel, to avoid a "hole" in the list */
X if (this != remain - 1) {
X coord last = freepix[remain - 1];
X freepix[this] = last;
X pix[last.x][last.y] = this;
X }
X
X /* Now set the value and decrease the number of remaining free pixels */
X pix[x][y] = value;
X remain--;
}
X
/*
X * makebm()
X *
X * Convert pix[x][y] to bitmap data format.
X */
void makebm()
{
X int i, j, x, y, k;
X i = 0;
X for (y = 0; y < height; y++) {
X j = 0; k = 0;
X for (x = 0; x < width; x++) {
X if (pix[x][y] == BLACK) k |= (1 << j);
X j++;
X if (j == 8) {
X bitmap[i++] = k;
X j = 0; k = 0;
X }
X }
X if (j > 0) {
X bitmap[i++] = k;
X }
X }
}
X
void rndbm()
{
X int k, x, y;
X
X srand48(time(0));
X init();
X
X /* Place white pixels until there are no more possibilities */
X while (remain > 0) {
X
X /* Select random using freelist */
X k = (int) floor(remain * drand48());
X x = freepix[k].x;
X y = freepix[k].y;
X
X /* Selected pixel becomes white, its neighbors black */
X set(x, y, WHITE);
X set(x - 1, y, BLACK);
X set(x + 1, y, BLACK);
X set(x, y - 1, BLACK);
X set(x, y + 1, BLACK);
X }
X
X makebm();
}
SHAR_EOF
$shar_touch -am 1013165494 'rndbg.c' &&
chmod 0644 'rndbg.c' ||
echo 'restore of rndbg.c failed'
shar_count="`wc -c < 'rndbg.c'`"
test 7194 -eq "$shar_count" ||
echo "rndbg.c: original size 7194, current size $shar_count"
fi
# ============= Imakefile ==============
if test -f 'Imakefile' && test X"$1" != X"-c"; then
echo 'x - skipping Imakefile (File already exists)'
else
echo 'x - extracting Imakefile (text)'
sed 's/^X//' << 'SHAR_EOF' > 'Imakefile' &&
X CC = gcc
X SYS_LIBRARIES = $(XLIB) -lm
X SRCS = rndbg.c
X OBJS = rndbg.o
X
ComplexProgramTarget(rndbg)
SHAR_EOF
$shar_touch -am 1013160594 'Imakefile' &&
chmod 0644 'Imakefile' ||
echo 'restore of Imakefile failed'
shar_count="`wc -c < 'Imakefile'`"
test 133 -eq "$shar_count" ||
echo "Imakefile: original size 133, current size $shar_count"
fi
# ============= Makefile.std ==============
if test -f 'Makefile.std' && test X"$1" != X"-c"; then
echo 'x - skipping Makefile.std (File already exists)'
else
echo 'x - extracting Makefile.std (text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.std' &&
XX11_INCLUDE_DIR=-I/usr/local/X11R5/include
XX11_LIB_DIR=-L/usr/local/X11R5/lib
X
rndbg: rndbg.o
X gcc -O2 -o rndbg rndbg.o $(X11_LIB_DIR) -lX11 -lm
X
rndbg.o: rndbg.c
X gcc -O2 -c rndbg.c $(X11_INCLUDE_DIR)
SHAR_EOF
$shar_touch -am 1013164894 'Makefile.std' &&
chmod 0644 'Makefile.std' ||
echo 'restore of Makefile.std failed'
shar_count="`wc -c < 'Makefile.std'`"
test 205 -eq "$shar_count" ||
echo "Makefile.std: original size 205, current size $shar_count"
fi
exit 0

---
----------------------------------------------------------------------
Niclas Wiberg ni...@isy.liu.se
Dept. of EE Linkoping University Sweden


exit 0 # Just in case...
--
// ch...@Sterling.COM | Send comp.sources.x submissions to:
\X/ Amiga: The only way to fly! | sour...@sterling.com
GCS d++(--) h++ s++:+ g+++(?) p? au(*)(0) a w+ v-(*) C++ US+++ P+ L+ 3 N++ K
!W M V-- -po+ Y+ t+ 5++ j- r+ G+ v b+++ D- b-- e+ u+ h- f+ r+++ !n y+++

0 new messages