v01i091: ALV - An Image Processing Toolkit, Part07/10
Charles Mcgrew
mcgrew at dartagnan.rutgers.edu
Tue Dec 12 06:30:34 AEST 1989
Submitted-by: everson at compsci.bristol.ac.uk
Posting-number: Volume 1, Issue 91
Archive-name: alv/part07
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 7 (of 10)."
# Contents: src/cst.c src/dsp.c src/glass.c
# Wrapped by everson at kukini on Tue Oct 17 07:45:13 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/cst.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/cst.c'\"
else
echo shar: Extracting \"'src/cst.c'\" \(8039 characters\)
sed "s/^X//" >'src/cst.c' <<'END_OF_FILE'
X/***************************************************************************/
X/* This program is a heavily-modified version of Phil Everson's winlev8 */
X/* from the ALV v2.1 suite of public domain image processing programs for */
X/* Sun workstations. It allows interactive thresholding and contrast */
X/* -stretching of greyscale images by manipulating the lookup tables (LUTs)*/
X/* Only greyscales from 1 to 254 are permitted. The LUTs can be saved to */
X/* a file for incorporation into a rasterfile header for the image. */
X/* */
X/* cst.c */
X/* */
X/* Bryan Dawson, Keele University Geography Dept (JANET: ged08 at keele.seq1) */
X/* 27/3/89 */
X/***************************************************************************/
X
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <suntool/panel.h>
X#include <stdio.h>
X#include "defs.h"
X
X#define CSTFONT "/usr/lib/fonts/fixedwidthfonts/cour.r.16"
X#define XSIZE 256
X#define YSIZE 256
X#define MaxY 254
X#define MinY 1
X
char *progname;
X
static short csticon[] =
X{
X#include "../images/icons/cst.icon"
X};
X
DEFINE_ICON_FROM_IMAGE(icon, csticon);
X
static void save_proc(),getcoords(), repaint_canvas(), invert0_proc(), quit_proc(), reset_proc();
int invert0 = 0,fcount = 0;
int yval = 255, xval = 127, lolim = MinY, hilim = MaxY;
char *progname;
XFILE * lutfile;
XFrame frame;
Canvas canvas;
Panel panel, inv_panel;
Pixfont *font;
Pixwin *pw, *pw2;
char cmsname[CMS_NAMESIZE];
u_char red[256], ref[256];/* all LUTs the same, so red used 3 times */
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
cst_main(argc, argv, envp)
X#endif
X int argc;
X char **argv;
X char **envp;
X
X{
X int i, j, x, y;
X u_char *pi;
X char *makethelabel();
X
X progname = strsave(argv[0]);
X parse_profile(&argc, argv, envp);/* link with support.c */
X
X while ((gc = getopt(argc, argv, " ")) != EOF)
X switch (gc) {
X case '?':
X errflag++;
X break;
X }
X
X if (errflag)
X error((char *) 0, "Usage: %s:\n", progname);
X
X if ((font = pf_open(CSTFONT)) == NULL) {
X fprintf(stderr, "%s : Cannot open %s\n", argv[0], CSTFONT);
X exit(1);
X }
X
X /* Initialise default grey scale ramp */
X for (i = 0; i < 256; i++) red[i] = ref[i] = i;
X red[0] = ref[0] = 255;
X red[255] = ref[255] = 0;
X
X /* create frame and canvas */
X frame = window_create(NULL, FRAME,
X FRAME_LABEL, makethelabel(),
X WIN_HEIGHT, YSIZE + 56,
X WIN_WIDTH, XSIZE + 10,
X FRAME_ICON, &icon,
X FRAME_ARGS, argc, argv,
X 0);
X
X panel = window_create(frame, PANEL, 0);
X
X inv_panel = panel_create_item(panel, PANEL_CYCLE,
X PANEL_CHOICE_STRINGS, "Normal", "Invert", 0,
X PANEL_NOTIFY_PROC, invert0_proc,
X 0);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, panel_button_image(panel, "Save", 0, 0),
X PANEL_NOTIFY_PROC, save_proc,
X 0);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, panel_button_image(panel, "Reset", 0, 0),
X PANEL_NOTIFY_PROC, reset_proc,
X 0);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, panel_button_image(panel, "Quit", 0, 0),
X PANEL_NOTIFY_PROC, quit_proc,
X 0);
X
X window_fit(panel);
X window_set(panel, WIN_WIDTH, XSIZE, 0);
X
X canvas = window_create(frame, CANVAS,
X WIN_BELOW, panel,
X WIN_X, 0,
X WIN_EVENT_PROC, getcoords,
X 0);
X
X /* get the canvas pixwin to draw into */
X pw = canvas_pixwin(canvas);
X
X /* Set colour map segment */
X pw_setcmsname(pw, "grays");
X pw_putcolormap(pw, 0, 256, red, red, red);
X
X window_set(canvas, WIN_CONSUME_PICK_EVENTS, LOC_DRAG, 0, 0);
X
X/* N.B. The Y origin is top left of window, not bottom left */
X pw_vector(pw, lolim, MaxY, hilim, MinY, PIX_SRC, 255);
X window_main_loop(frame);
X}
X
static void
repaint_canvas()
X{
pw_writebackground(pw,0,0,256,256,PIX_SRC);
X}
X
static void
invert0_proc(item, value, event)
X Panel_item item;
X int value;
X Event *event;
X{
register int p;
X invert0 = value;
for (p=0;p<256;p++) red[p] = 255 - red[p];
X setcolormap();
X}
X
static void
getcoords(canvas, event, arg)
X Canvas canvas;
X Event *event;
X caddr_t arg;
X{
X register int q;
X char *makethelabel();
X
X switch(event_id(event))
X {
X case LOC_DRAG :
X case MS_MIDDLE:
X repaint_canvas(); /* clear window */
X yval = 255 - event_y(event); /* where's the cursor ? */
X xval = event_x(event);
X if (xval < lolim) xval = lolim; /* trap over/under ranges */
X if (xval > hilim) xval = hilim;
X pw_vector(pw,lolim,255,xval,255 - yval,PIX_SRC,255);
X pw_vector(pw,xval,255 - yval,hilim,0,PIX_SRC,255);
X stretchlut(lolim,MinY,xval,yval,0);
X stretchlut(xval,yval,hilim,MaxY,yval);
X if (invert0) for (q=1;q<255;q++) red[q] = 255 - red[q];
X pw_putcolormap(pw, 0, 256, red, red, red);
X break;
X case MS_LEFT :
X repaint_canvas();
X lolim = event_x(event);
X if (lolim >= hilim) lolim = hilim - 1;
X pw_vector(pw,lolim,255,hilim,0,PIX_SRC,255);
X stretchlut(lolim,MinY,hilim,MaxY,0);
X if (invert0) for (q=1;q<255;q++) red[q] = 255 - red[q];
X pw_putcolormap(pw, 0, 256, red, red, red);
X window_set(frame,FRAME_LABEL,makethelabel(),0);
X break;
X case MS_RIGHT :
X repaint_canvas();
X hilim = event_x(event);
X if (hilim <= lolim) hilim = lolim + 1;
X pw_vector(pw,lolim,255,hilim,0,PIX_SRC,255);
X stretchlut(lolim,MinY,hilim,MaxY,0);
X if (invert0) for (q=1;q<255;q++) red[q] = 255 - red[q];
X pw_putcolormap(pw, 0, 256, red, red, red);
X window_set(frame,FRAME_LABEL,makethelabel(),0);
X break;
X } /* end of switch */
X}
X
stretchlut(lox,loy,hix,hiy,base)
int lox,loy,hix,hiy,base;
X{
int i,rangex,rangey,temp;
double a;
X
X rangex = hix - lox + 1;
X rangey = hiy - loy + 1;
X a = (double)rangey / (double)rangex; /* scaling factor */
for (i=MinY;i<lolim;i++) red[i] = 0;
for (i=hilim;i<MaxY;i++); red[i] = 255;
for (i=lox;i<hix;i++)
X {
X temp = (int)((i - lox + 1) * a); /* offset & gain compensation */
X temp += base; /* for top of two-part stretch */
X if (temp < 1) temp = 1; /* avoid exteme values - used for text */
X if (temp > 254) temp = 254;
X red[i] = (unsigned char)temp;
X }
X}
X
setcolormap()
X{
int i;
X
X/* Initialise variables used to set colour map */
red[0] = 255;
red[255] = 0;
pw_putcolormap(pw, 0, 256, red, red, red);
X}
X
char *
makethelabel()
X{
X static char buf[BUFSIZ];
X char *sprintf();
X return sprintf(buf, "Lolim = %3d Hilim = %3d", lolim, hilim);
X}
X
static void
quit_proc()
X{
X window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);
X window_destroy(frame);
X}
X
static void
reset_proc()
X{
register int i;
X
X repaint_canvas(); /* clear window & redraw line */
X pw_vector(pw,lolim,MaxY,hilim,MinY,PIX_SRC,255);
X
X invert0 = 0; /* reset normal/invert0 toggle */
X panel_set_value(inv_panel, invert0);
X
X for (i = 0; i < 256; i++) red[i] = i; /* plain ramp */
X setcolormap();
X
X lolim = MinY; hilim = MaxY; /* default labels */
X window_set(frame, FRAME_LABEL, makethelabel(), 0);
X}
X
static void
save_proc()
X{
int id;
char fname[10];
X
sprintf(fname,"clut.%03d",++fcount);
lutfile = fopen(fname,"w");
id = fwrite(red,1,256,lutfile);
id = fwrite(red,1,256,lutfile);
id = fwrite(red,1,256,lutfile);
id = fclose(lutfile);
X}
END_OF_FILE
if test 8039 -ne `wc -c <'src/cst.c'`; then
echo shar: \"'src/cst.c'\" unpacked with wrong size!
fi
# end of 'src/cst.c'
fi
if test -f 'src/dsp.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/dsp.c'\"
else
echo shar: Extracting \"'src/dsp.c'\" \(11523 characters\)
sed "s/^X//" >'src/dsp.c' <<'END_OF_FILE'
X#include "defs.h"
X#include <fcntl.h>
X
X#define DEFAULT_WIN_XSIZE 850
X#define DEFAULT_WIN_YSIZE 1000
X#define MIN_WIN_XSIZE 200
X#define MIN_WIN_YSIZE 200
X
XFrame frame;
Canvas canvas;
Cursor cursor;
Icon icon;
Panel panel;
Panel_item window_slider, level_slider;
Pixwin *pw, *fpw;
Pixrect *pr, *dpr, *icon_pr, *backing_pixrect, *mem_create();
X
static short dspicon[] =
X{
X#include "../images/icons/dsp.icon"
X};
DEFINE_ICON_FROM_IMAGE(bwicon, dspicon);
X
Menu canvas_menu;
static void
getcoords(), window_proc(), level_proc(), canvas_proc(),
repaint_canvas(), resize_canvas();
X
char cmsname[BUFSIZ];
u_char red[256], green[256], blue[256];
char *progname;
char *filename;
char *eight_to_one;
char buf1[BUFSIZ];
int window, level;
int old_level, old_window;
int max_level, min_level;
int lower, upper;
int table[10000];
int winxsize, winysize;
int size, wl, colour;
colormap_t colormap;
Panel_item next_butt, prev_butt;
static void dummy_proc(), canvas_event_proc();
X
X#ifdef STANDALONE
main(argc, argv, envp)
X#else
dsp_main(argc, argv, envp)
X#endif
X int argc;
X char **argv;
X char **envp;
X{
X int i;
X int scroll_thickness;
X float calc_mean();
X Pixrect *call_dither();
X
X eight_to_one = NULL;
X progname = strsave(argv[0]);
X parse_profile(&argc, argv, envp);
X
X filename = strsave("stdin");
X while ((gc = getopt(argc, argv, "W:bc8:")) != EOF)
X switch (gc) {
X case '8':
X eight_to_one = strsave(optarg);
X break;
X case '?':
X errflag++;
X break;
X }
X
X if (errflag)
X error((char *) 0, "Usage: %s: [-8 program] [infile]\n", progname);
X
X for (stream = 0; optind < argc; stream++, optind++)
X if (stream == 0 && strcmp(argv[optind], "-") != 0) {
X filename = strsave(argv[optind]);
X if (freopen(argv[optind], mode[stream], f[stream]) == NULL)
X error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
X }
X if (eight_to_one == NULL)
X eight_to_one = strsave(FILTER8TO1);
X
X if ((pr = pr_load(stdin, &colormap)) == NULL)
X error(PR_IO_ERR_RASREAD);
X
X frame = window_create(NULL, FRAME, FRAME_NO_CONFIRM, TRUE, 0);
X canvas = window_create(frame, CANVAS, 0);
X pw = canvas_pixwin(canvas);
X colour = iscolour(pw);
X window_destroy(frame);
X
X if (!colour) {
X if (pr->pr_depth == 8)
X pr = call_dither(pr);
X if (pr->pr_depth > 8)
X error("Input depth not supported on this workstation");
X }
X
X setup_windowsizes();
X
X scroll_thickness = defaults_get_integer("/Scrollbar/Thickness", 14, 0);
X frame = window_create(NULL, FRAME,
X FRAME_LABEL, filename,
X WIN_HEIGHT, winysize + scroll_thickness + 7,
X WIN_WIDTH, winxsize + scroll_thickness + 10,
X FRAME_ARGS, argc, argv,
X 0);
X
X if (colour) {
X setup_colourmap();
X if (colormap.length != 0) {
X if (!mono_override)
X allow_mono(pr);
X }
X }
X
X max_level = calc_max(pr)+1;
X if (pr->pr_depth > 8 && colormap.length == 0) {
X window = MAXLEVEL(8);
X level = (int) calc_mean(pr);
X old_window = max_level;
X old_level = max_level / 2;
X setup_scrollbars();
X }
X cursor = cursor_create(
X CURSOR_OP, PIX_SRC ^ PIX_DST,
X CURSOR_CROSSHAIR_LENGTH, 20,
X CURSOR_SHOW_CROSSHAIRS, TRUE,
X 0);
X
X canvas = window_create(frame, CANVAS,
X WIN_CURSOR, cursor,
X CANVAS_HEIGHT, pr->pr_size.y,
X CANVAS_WIDTH, pr->pr_size.x,
X CANVAS_AUTO_SHRINK, FALSE,
X WIN_EVENT_PROC, canvas_event_proc,
X WIN_CONSUME_PICK_EVENT, LOC_MOVE,
X 0);
X
X if (pr->pr_depth > 8)
X window_set(canvas, WIN_BELOW, panel, WIN_X, 0, 0);
X
X pw = canvas_pixwin(canvas);
X
X window_set(canvas,
X WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
X WIN_HORIZONTAL_SCROLLBAR, scrollbar_create(0),
X 0);
X
X if (pr->pr_depth <= 8)
X dpr = pr;
X else {
X if ((dpr = mem_create(pr->pr_size.x, pr->pr_size.y, 8)) == NULL)
X error("mem_create returned NULL");
X min_level = 0;
X setup_table();
X convert_to_8bits(pr, dpr);
X }
X
X if (pr->pr_depth == 1 || !colour)
X window_set(frame, FRAME_ICON, &bwicon, 0);
X else {
X icon_pr = mem_create(64, 64, 8);
X paint_icon();
X }
X
X pw_rop(pw, 0, 0, dpr->pr_size.x, pr->pr_size.y, PIX_SRC, dpr, 0, 0);
X window_main_loop(frame);
X}
paint_icon()
X{
X subsample(dpr, icon_pr);
X
X icon = icon_create(ICON_IMAGE, icon_pr, 0);
X window_set(frame, FRAME_ICON, icon, 0);
X}
subsample(in, out)
X Pixrect *in, *out;
X{
X int cvx, cvy, lcx, lcy, hcx, hcy;
X register int i, j, i1, j1;
X int total;
X
X cvx = (100 * in->pr_size.x) / out->pr_size.x;
X cvy = (100 * in->pr_size.y) / out->pr_size.y;
X
X for (j = 0; j < out->pr_size.y; j++)
X for (i = 0; i < out->pr_size.x; i++) {
X hcx = i * cvx / 100;
X hcy = j * cvy / 100;
X lcx = (i - 1) * cvx / 100 + 1;
X lcy = (j - 1) * cvy / 100 + 1;
X lcx = (lcx < 0) ? 0 : (lcx > hcx) ? hcx : lcx;
X lcy = (lcy < 0) ? 0 : (lcy > hcy) ? hcy : lcy;
X
X total = 0;
X for (j1 = lcy; j1 <= hcy; j1++)
X for (i1 = lcx; i1 <= hcx; i1++)
X total += pr_get(in, i1, j1);
X pr_put(out, i, j, (total / ((hcx + 1 - lcx) * (hcy + 1 - lcy))));
X }
X}
setup_scrollbars()
X{
X setup_font();
X
X panel = window_create(frame, PANEL,
X WIN_WIDTH, WIN_EXTEND_TO_EDGE,
X 0);
X
X window_slider = panel_create_item(panel, PANEL_SLIDER,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(0),
X PANEL_LABEL_FONT, font,
X PANEL_LABEL_STRING, "Window:",
X PANEL_VALUE, window,
X PANEL_MIN_VALUE, 0,
X PANEL_MAX_VALUE, max_level,
X PANEL_NOTIFY_PROC, window_proc,
X 0);
X
X level_slider = panel_create_item(panel, PANEL_SLIDER,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(1),
X PANEL_LABEL_FONT, font,
X PANEL_LABEL_STRING, "Level :",
X PANEL_VALUE, level,
X PANEL_MIN_VALUE, 0,
X PANEL_MAX_VALUE, max_level,
X PANEL_NOTIFY_PROC, level_proc,
X 0);
X
X window_fit_height(panel);
X}
X
static void
window_proc(item, value, event)
X Panel_item item;
X int value;
X Event *event;
X{
X int ol;
X
X ol = level;
X window = value;
X
X if (level + window / 2 >= max_level)
X level = max_level - window / 2;
X if (level - window / 2 < min_level)
X level = window / 2;
X if (ol != level)
X panel_set(level_slider, PANEL_VALUE, level, 0);
X setup_table();
X convert_to_8bits(pr, dpr);
X pw_rop(pw, 0, 0, dpr->pr_size.x, pr->pr_size.y, PIX_SRC, dpr, 0, 0);
X paint_icon();
X}
X
static void
level_proc(item, value, event)
X Panel_item item;
X int value;
X Event *event;
X{
X level = value;
X
X if (level + window / 2 >= max_level)
X level = max_level - window / 2;
X if (level - window / 2 < min_level)
X level = window / 2;
X if (level != value)
X panel_set(level_slider, PANEL_VALUE, level, 0);
X setup_table();
X convert_to_8bits(pr, dpr);
X pw_rop(pw, 0, 0, dpr->pr_size.x, pr->pr_size.y, PIX_SRC, dpr, 0, 0);
X paint_icon();
X}
X/* initialise lookup table for current window & level */
setup_table()
X{
X register int i;
X register int *t;
X register int new_lower, new_upper;
X int old_lower, old_upper;
X double m, cumulative_greylevel;
X
X if (window != 0)
X m = (253.) / (float) (window); /* 253 = No. greylevels
X * - 1 */
X
X cumulative_greylevel = 1.;
X new_lower = level - window / 2;
X new_upper = level + window / 2;
X old_lower = old_level - old_window / 2;
X old_upper = old_level + old_window / 2;
X
X lower = MIN(old_lower, new_lower);
X upper = MAX(old_upper, new_upper);
X
X lower = 0;
X upper = max_level;
X t = &table[lower];
X for (i = lower; i < upper; i++)
X if (i <= new_lower)
X *t++ = 1;
X else if (i >= new_upper)
X *t++ = 254;
X else {
X *t++ = cumulative_greylevel;
X cumulative_greylevel += m;
X }
X old_level = level;
X old_window = window;
X}
convert_to_8bits(in, out)
X Pixrect *in, *out;
X{
X short *ptr16;
X int *ptr32;
X char *ptr8;
X register int i;
X int n;
X int mode = TRUE;
X
X#define ALL_PIXELS TRUE
X
X ptr8 = (char *) mpr_d(out)->md_image;
X n = in->pr_size.x * in->pr_size.x;
X
X switch (in->pr_depth) {
X case 16:
X ptr16 = (short *) mpr_d(in)->md_image;
X for (i = 0; i < n; i++) {
X if ((mode == ALL_PIXELS) || ((*ptr16 >= lower) && (*ptr16 <= upper)))
X *ptr8 = *(table + (*ptr16));
X ptr8++;
X ptr16++;
X }
X break;
X case 32:
X ptr32 = (int *) mpr_d(in)->md_image;
X for (i = 0; i < n; i++) {
X if ((mode == ALL_PIXELS) || ((*ptr32 >= lower) && (*ptr32 <= upper)))
X *ptr8 = *(table + (*ptr32));
X ptr8++;
X ptr16++;
X }
X break;
X }
X}
setup_windowsizes()
X{
X if (pr->pr_size.x > DEFAULT_WIN_XSIZE)
X winxsize = DEFAULT_WIN_XSIZE;
X else
X winxsize = MAX(pr->pr_size.x, MIN_WIN_XSIZE)+3;
X
X if (pr->pr_size.y > DEFAULT_WIN_YSIZE)
X winysize = DEFAULT_WIN_YSIZE;
X else
X winysize = MAX(pr->pr_size.y, MIN_WIN_YSIZE)+17;
X}
setup_colourmap()
X{
X register int i;
X
X for (i = 0; i < 256; i++) {
X red[i] = green[i] = blue[i] = -1;
X }
X fpw = (Pixwin *) window_get(frame, WIN_PIXWIN);
X
X if (colormap.type == RMT_NONE || colormap.length == 0) {
X sprintf(cmsname, "greyscale%d", pr->pr_depth);
X
X pw_setcmsname(fpw, cmsname);
X
X for (i = 1; i < 255; i++) {
X red[i] = i;
X green[i] = i;
X blue[i] = i;
X }
X if (mono_override) {
X red[255] = blue[255] = green[255] = 255;
X red[0] = blue[0] = green[0] = 0;
X }
X pw_putcolormap(fpw, 0, 256, red, green, blue);
X } else {
X pw_setcmsname(fpw, "non_greyscale");
X pw_putcolormap(fpw, 0, colormap.length, colormap.map[0], colormap.map[1], colormap.map[2]);
X }
X window_set(frame, FRAME_INHERIT_COLORS, TRUE, 0);
X}
X
float
calc_mean(pr)
X Pixrect *pr;
X{
X register int i, j;
X int sum;
X
X sum = 0;
X for (j = 0; j < pr->pr_size.y; j++)
X for (i = 0; i < pr->pr_size.x; i++)
X sum += pr_get(pr, i, j);
X
X return (sum / (pr->pr_size.x * pr->pr_size.y));
X}
X
static void
canvas_event_proc(canvas, event, arg)
X Canvas canvas;
X Event *event;
X caddr_t arg;
X{
X char buf[BUFSIZ];
X
X if (event_id(event) == LOC_MOVE || event_is_button(event)) {
X sprintf(buf, "%s - %d, %d = %d", filename, event_x(event), event_y(event), pr_get(pr, event_x(event), event_y(event)));
X window_set(frame, FRAME_LABEL, buf, 0);
X }
X}
iscolour(pw)
X Pixwin *pw;
X{
X
X return ((pw->pw_pixrect->pr_depth > 1) ? TRUE : FALSE);
X}
X
Pixrect *
call_dither(in)
X Pixrect *in;
X{
X Pixrect *out, *pr_load();
X FILE *fp_tochild;
X FILE *fp_fromchild;
X int childpid;
X int pfdout[2], pfdin[2];
X int c, numfds;
X
X if (pipe(pfdout) == -1 || pipe(pfdin) == -1) {
X perror(progname);
X exit(1);
X }
X switch (childpid = fork()) {
X case -1:
X perror(progname);
X exit(1);
X case 0:
X if (close(0) == -1)
X perror(progname);
X if (dup(pfdout[0]) != 0)
X perror(progname);
X if (close(1) == -1)
X perror(progname);
X if (dup(pfdin[1]) != 1)
X perror(progname);
X if (close(pfdout[0]) == -1 || close(pfdout[1]) == -1 || close(pfdin[0]) == -1 || close(pfdin[1]) == -1)
X perror(progname);
X execlp(eight_to_one, eight_to_one, 0);
X perror(eight_to_one);
X exit(1);
X default:
X if (close(pfdout[0]) == -1 || close(pfdin[1]) == -1)
X perror(progname);
X
X if ((fp_tochild = fdopen(pfdout[1], "w")) == NULL)
X error("Can't get file descriptor to write to child process");
X if (pr_dump(in, fp_tochild, NULL, RT_STANDARD, 0) == PIX_ERR)
X error("pr_dump returned PIX_ERR");
X fclose(fp_tochild);
X
X if ((fp_fromchild = fdopen(pfdin[0], "r")) == NULL)
X error("Can't get file descriptor to read from child process");
X if ((out = pr_load(fp_fromchild, NULL)) == NULL)
X error("pr_load returned NULL");
X fclose(fp_tochild);
X }
X return out;
X}
X
allow_mono(pr)
Pixrect *pr;
X{
X register int i, j, pix;
X
X for(i=0;i<pr->pr_size.x;i++)
X for(j=0;j<pr->pr_size.y;j++)
X if ((pix = pr_get(pr, i, j)) == 255 || pix == 254)
X pr_put(pr, i, j, 253);
X else if (pix == 0)
X pr_put(pr, i, j, 1);
X}
END_OF_FILE
if test 11523 -ne `wc -c <'src/dsp.c'`; then
echo shar: \"'src/dsp.c'\" unpacked with wrong size!
fi
# end of 'src/dsp.c'
fi
if test -f 'src/glass.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/glass.c'\"
else
echo shar: Extracting \"'src/glass.c'\" \(16203 characters\)
sed "s/^X//" >'src/glass.c' <<'END_OF_FILE'
X/*
X * Magnifying glass (for Sun-3 workstations)
X *
X * Copyright 1986, 1987 by Scott Schwartz
X * This program may be copied with the provision that this copyright
X * message remains, and that further distribution of this code and it's
X * derivatives is not subject to additional restrictions.
X *
X * Lots of changes, but no Copyright, by Mark Weiser.
X *
X * compile with -lsuntool -lsunwindow -lpixrect
X *
X * vi: set ts=8
X *
X * revision history:
X * 10 Nov 86 initial coding Scott Schwartz
X *
X * version 1.0 25 Nov 86
X * modified to draw big pixels with raster-ops ses
X *
X * version 1.1 27 Jan 87
X * does magnification in memory, ses
X * to avoid screen access
X *
X * version 1.2 27 Jan 87
X * flood destination with white, ses/af
X * then draw only black spots
X *
X * version 2.0 15 Apr 87 mark weiser
X * vastly faster magnification algorithm using only 2k blits
X * instead of k**2 (where k is the height or width of the final).
X * Also added a panel for friendliness, and stopped using *all* the cpu!
X *
X * version 2.1 17 Apr 87 mark weiser
X * added locking.
X *
X * version 2.2 20 Apr 87 mark weiser
X * added changes for color suns (not tested here).
X *
X * version 2.3 6 June 87 Ed Falk
X * general clean-up, made to work with color suns.
X * minor performance improvements. Locking around the
X * initial screen read in order to get garbage out of
X * image.
X */
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/ioctl.h>
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <suntool/panel.h>
X#include <suntool/textsw.h>
X#include <pixrect/pixrect_hs.h>
X
X/* I HATE these macros -mdw */
X#undef min
X#undef max
X
X
X/* useful macros */
X#define ERROR(msg) { fprintf(stderr, "%s: %s\n", argv[0], msg); exit(1); }
X
X/* forward declarations */
extern char *getenv(), *sprintf();
extern Notify_error notify_dispatch();
static Notify_value notice_destroy_event();
static Notify_value update_value_proc();
static Notify_value update_mag_proc();
static void pw_mag();
static void view();
static void update();
static void glass_time_proc();
static void lock_proc(), unlock_proc();
static void repaint_proc(), resize_proc() ;
X
X/* constants */
static char frame_label[] = "Magnifying Glass 2.3";
static short icon_image[] = {
X#include "../images/icons/glass.icon"
X};
DEFINE_ICON_FROM_IMAGE(icon, icon_image);
X#define NILPR ((struct pixrect *)0)
X#define MAX_MAG 32
X
X/* global vars */
static struct pixrect *tmpsrc; /* working space, to avoid screen access */
static struct pixrect *tmpdst;
static int done = 0;
struct pixrect *srcpr; /* the source pixrect, i.e. the whole screen */
int rootfd; /* file descriptor for root window, for cursor location */
X
X/* things to draw on */
Panel panel;
XFrame frame; /* the actual window frame */
Canvas canvas; /* our particular canvas, filling the frame */
X
int mag = 1; /* magnification in output window */
int delay = 1000;
int locked = 0;
int locked_x, locked_y;
Panel_item time_left_item;
X
X/*
X * main routine
X */
main(argc,argv)
int argc;
char **argv;
X{
X char *parent; /* name of the parent window, usually win0 */
X char *magstr = "x99999"; /* allocate space for actual string */
X int retcode;
X Pixwin *canvas_pw ;
X int w, h ;
X
X /* create output window */
X frame = window_create(NULL, FRAME,
X FRAME_LABEL, frame_label,
X FRAME_ICON, &icon,
X FRAME_ARGC_PTR_ARGV, &argc, argv,
X /* WIN_ERROR_MSG, "Can't create Frame", */
X 0);
X
X panel = window_create(frame, PANEL, 0);
X (void) panel_create_item(panel, PANEL_SLIDER,
X PANEL_LABEL_STRING, "Mag:",
X PANEL_VALUE, mag,
X PANEL_MIN_VALUE, 1,
X PANEL_MAX_VALUE, MAX_MAG,
X PANEL_SHOW_RANGE, FALSE,
X PANEL_SHOW_VALUE, TRUE,
X PANEL_SLIDER_WIDTH, 100,
X PANEL_NOTIFY_PROC, update_mag_proc,
X PANEL_CLIENT_DATA, &mag,
X 0);
X (void) panel_create_item(panel, PANEL_SLIDER,
X PANEL_LABEL_STRING, "Delay:",
X PANEL_VALUE, 10000,
X PANEL_MIN_VALUE, 1000,
X PANEL_MAX_VALUE, 999999,
X PANEL_SHOW_RANGE, FALSE,
X PANEL_SHOW_VALUE, FALSE,
X PANEL_SLIDER_WIDTH, 100,
X PANEL_NOTIFY_PROC, update_value_proc,
X PANEL_CLIENT_DATA, &delay,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(1),
X 0);
X
X (void) panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, panel_button_image(panel, "Lock", 6, 0),
X PANEL_NOTIFY_PROC, lock_proc,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(2),
X 0);
X
X (void) panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, panel_button_image(panel, "Unlock", 6, 0),
X PANEL_NOTIFY_PROC, unlock_proc,
X 0);
X
X time_left_item = panel_create_item(panel, PANEL_SLIDER,
X PANEL_LABEL_STRING, "Time Left:",
X PANEL_VALUE, 10,
X PANEL_MIN_VALUE, 0,
X PANEL_MAX_VALUE, 10,
X PANEL_SHOW_RANGE, FALSE,
X PANEL_SHOW_VALUE, FALSE,
X PANEL_SLIDER_WIDTH, 100,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(2),
X PANEL_SHOW_ITEM, FALSE,
X 0);
X window_fit_height(panel);
X
X /* gather data on output pixwin */
X canvas = window_create(frame, CANVAS,
X WIN_HEIGHT, 200,
X WIN_WIDTH, 200,
X CANVAS_RESIZE_PROC, resize_proc,
X CANVAS_REPAINT_PROC, repaint_proc,
X CANVAS_RETAINED, FALSE,
X WIN_IGNORE_PICK_EVENTS, MS_RIGHT,
X MS_MIDDLE, MS_LEFT, 0,
X 0);
X
X window_fit(frame);
X
X canvas_pw = canvas_pixwin(canvas);
X
X /* open rootwindow */
X parent = getenv("WINDOW_PARENT");
X if (parent==NULL)
X ERROR("can't get WINDOW_PARENT from environment.")
X rootfd = open(parent, O_RDONLY, 0);
X if (rootfd<0)
X perror(argv[0]);
X
X /* open frame buffer */
X srcpr = canvas_pw->pw_pixrect ;
X
X /* set color table from frame buffer's color table */
X
X {
X unsigned char red[256], green[256], blue[256] ;
X pr_getcolormap(srcpr, 0, 256, red, green, blue) ;
X pw_setcmsname(canvas_pw, "glass") ;
X pw_putcolormap(canvas_pw, 0, 256, red, green, blue) ;
X }
X
X /* handle arguments */
X if (argc > 1) {
X retcode = sscanf(argv[1], "%d", &mag);
X if (retcode <= 0)
X ERROR("\
problem evaluating arguments\n\
Usage: glass magnification [suntools-options]");
X mag = (mag > MAX_MAG) ? MAX_MAG : mag;
X }
X
X /* allocate static pixrects */
X w = (int) window_get(canvas, WIN_WIDTH) ;
X h = (int) window_get(canvas, WIN_HEIGHT) ;
X tmpdst = mem_create(w, h, srcpr->pr_depth);
X
X /* set up an interposed event handler so we know when to quit */
X (void)notify_interpose_destroy_func(frame, notice_destroy_event);
X
X /* start us in a second */
X do_with_delay(glass_time_proc, 1, 0);
X
X /* copy input to output forever */
X window_main_loop(frame);
X exit(0);
X}
X
X
X
static void
resize_proc(canvas, width, height)
X Canvas canvas ;
X int width, height ;
X{
X int w,h ;
X
X /* destroy and re-allocate temporary pixrects */
X
X pr_destroy(tmpdst) ;
X
X w = width ;
X h = height ;
X tmpdst = mem_create(w, h, srcpr->pr_depth);
X}
X
X
X
X
static void
repaint_proc(canvas, pw, repaint_area)
X Canvas canvas ;
X Pixwin *pw ;
X Rectlist *repaint_area ;
X{
X view(rootfd, srcpr, canvas, mag);
X}
X
X
X
X
X/*
X * Thing to do at intervals.
X */
static void
glass_time_proc()
X{
X if (done) return;
X if (window_get(frame, FRAME_CLOSED)) {
X do_with_delay(glass_time_proc, 2, 0);
X } else {
X view(rootfd, srcpr, canvas, mag);
X do_with_delay(glass_time_proc, 0, delay);
X }
X}
X
X/*
X * view does the work of displaying the (possibly) magnified image
X * at the location indicated by rootfd (mouse). view copies srcpr to dstpw.
X */
static void
view(rootfd, srcpr, canvas, mag)
X int rootfd; /* root window, for mouse data */
X struct pixrect *srcpr; /* screen source pixrect */
X Canvas canvas;
X int mag;
X{
X /* constants */
X int maxy = (srcpr->pr_size.y);
X int maxx = (srcpr->pr_size.x);
X Pixwin *dstpw = canvas_pixwin(canvas);
X
X /* local vars */
X int x,y;
X int w, h;
X
X /*
X * read mouse coords from vuid register. sadly, the sunview
X * programmers guide is not clear on this. appendix A tells some,
X * but you have to look at <sundev/vuid_event.h> to see what
X * virtual events you can find out about. luckily, the mouse is
X * one of them.
X */
X if (locked) {
X x = locked_x;
X y = locked_y;
X } else {
X x = win_get_vuid_value(rootfd, LOC_X_ABSOLUTE);
X y = win_get_vuid_value(rootfd, LOC_Y_ABSOLUTE);
X }
X
X /*
X * find out how big our drawing surface is.
X */
X w = (int) window_get(canvas, CANVAS_WIDTH);
X h = (int) window_get(canvas, CANVAS_HEIGHT);
X
X /*
X * draw on it.
X */
X if (mag<=1) {
X x = min(maxx-w, max(x-w, 0));
X y = min(maxy-h, max(y-h, 0));
X update(dstpw, 0, 0, w, h, PIX_SRC, srcpr, x, y);
X }
X else {
X x = min(maxx-w/mag, max(x-w/mag, 0));
X y = min(maxy-h/mag, max(y-h/mag, 0));
X pw_mag(dstpw, 0, 0, w, h, mag, srcpr, x, y);
X }
X}
X
X/*
X * pw_mag copies a magnified view of spr to dpw using pixel replication.
X * the arguments are the same as those to the pw_rop library call, except
X * that magnification is passed instead of raster-op.
X */
static void
pw_mag(dpw, dx, dy, w, h, mag, spr, sx, sy)
X Pixwin *dpw; /* destination pixwin */
X int dx, dy; /* destination x,y */
X int w, h; /* width and height of block to copy */
X int mag; /* magnification */
X struct pixrect *spr; /* source pixrect */
X int sx,sy; /* location in source to copy from */
X{
X /* locals */
X register int xmax, ymax ;
X register int x, y, delta, cnt ;
X register int x0, y0 ;
X Rect lock_rect ;
X
X /* w,h are maximum output (magnified) dimensions; xmax,ymax are
X maximum input dimensions, rounded up */
X
X xmax = (w+mag-1)/mag ;
X ymax = (h+mag-1)/mag ;
X
X /* make off-screen copy of source */
X /* KLUDGE: pixrect and pixwin operations will interfere with
X each other, causing garbage to appear in the canvas if
X the cursor is being moved during the pr_rop. By locking
X something (anything) during the pr_rop, we avoid this problem */
X
X lock_rect.r_left = lock_rect.r_top = 0 ;
X lock_rect.r_width = w ; lock_rect.r_height = h ;
X pw_lock(dpw, &lock_rect) ;
X pr_rop(tmpdst, 0, 0, xmax, ymax, PIX_SRC|PIX_DONTCLIP, spr, sx, sy);
X pw_unlock(dpw) ;
X
X
X delta = xmax*mag - w ; /* error term */
X x0 = xmax-1; cnt = mag-delta ;
X for(x = w-1; x>=0; --x)
X {
X pr_rop(tmpdst, x, 0, 1, ymax, PIX_SRC|PIX_DONTCLIP, tmpdst, x0, 0);
X if(--cnt <= 0)
X {
X cnt = mag ;
X --x0 ;
X }
X }
X
X delta = ymax*mag - h ; /* error term */
X y0 = ymax-1; cnt = mag-delta ;
X for(y = h-1; y>=0; --y)
X {
X pr_rop(tmpdst, 0, y, w, 1, PIX_SRC|PIX_DONTCLIP, tmpdst, 0, y0);
X if(--cnt <= 0)
X {
X cnt = mag ;
X --y0 ;
X }
X }
X
X
X /* draw */
X update(dpw, dx, dy, w, h, PIX_SRC, tmpdst, 0, 0);
X}
X
X/* for debugging purposes, mostly */
static void
update(dpw, dx, dy, w, h, mag, spr, sx, sy)
X Pixwin *dpw; /* destination pixwin */
X int dx, dy; /* destination x,y */
X int w, h; /* width and height of block to copy */
X int mag; /* magnification */
X struct pixrect *spr;
X /* source pixrect */
X int sx,sy; /* location in source to copy from */
X{
pw_rop(dpw, dx, dy, w, h, mag, spr, sx, sy);
X}
X
X
X/*
X * a service routine that gets called when the frame is destroyed
X * by someone selecting 'quit'. this is basically right out of the
X * manual.
X */
static Notify_value
notice_destroy_event(frame, status)
X Frame *frame;
X Destroy_status status;
X{
X if (status != DESTROY_CHECKING) {
X done = 1;
X }
X return (notify_next_destroy_func(frame,status));
X}
X
X/*
X * The routines below I have found enormously handy when dispatching
X * things via the notifier. Use them in good health, or bad. I do.
X * -mark weiser
X */
X
X/*
X * Call procedure f in a little while.
X */
do_with_delay(f, secs, usecs)
void (*f)();
int secs, usecs;
X{
X Notify_value do_the_call();
X struct itimerval timer;
X
X /* Sigh, so much work just to wait a bit before starting up. */
X timer.it_interval.tv_usec = 0;
X timer.it_interval.tv_sec = 0;
X timer.it_value.tv_usec = usecs;
X timer.it_value.tv_sec = secs;
X notify_set_itimer_func(f, do_the_call,
X ITIMER_REAL, &timer, NULL);
X}
X
X/*
X * Wrapper to make sure procedures from do_with_delay return good values
X * to the notifier.
X */
Notify_value
do_the_call(f, which)
void (*f)();
X{
X (*f)();
X return NOTIFY_DONE;
X}
X
static Notify_value
update_mag_proc(item, value)
X Panel_item item;
X int value ;
X{
X int width, height ;
X width = (int) window_get(canvas, WIN_WIDTH) ;
X height = (int) window_get(canvas, WIN_HEIGHT) ;
X mag = value;
X resize_proc(canvas, width, height) ;
X return NOTIFY_DONE;
X}
X
X
static Notify_value
update_value_proc(item, value)
X Panel_item item;
X int value ;
X{
X int *ptr;
X ptr = (int *)panel_get(item, PANEL_CLIENT_DATA);
X *ptr = value;
X return NOTIFY_DONE;
X}
X
static void
lock_proc(item, event)
X Panel_item;
X Event *event;
X{
X extern void do_the_lock();
X popup_msg(frame, event,
X "After buttoning 'Done' in this window,\n\
you will have ten (10) seconds to put the\n\
cursor someplace. At the end of 10 seconds,\n\
glass will be locked into looking at that position.");
X locked = 0;
X}
X
static void
unlock_proc()
X{
X locked = 0;
X}
X
static void
do_the_lock()
X{
X static void popup_textsw_done();
X locked_x = win_get_vuid_value(rootfd, LOC_X_ABSOLUTE);
X locked_y = win_get_vuid_value(rootfd, LOC_Y_ABSOLUTE);
X locked = 1;
X}
X
X/*
X * The stuff below is some standard hacks I have started using,
X * especially in the 'sdi' game. I have inserted them here for convenience.
X * -mark weiser
X */
X
static Frame popup_frame = NULL;
static Textsw popup_text;
static Panel popup_panel;
static Panel_item popup_msg_item;
static void popup_yes_proc(), popup_no_proc(), popup_textsw_done();
X
X/*
X * Fake an event, so anyone can popup a message.
X */
easy_pop(msg)
char *msg;
X{
X Event event;
X event_x(&event) = (int)window_get(frame, WIN_X);
X event_y(&event) = (int)window_get(frame, WIN_Y);
X popup_msg(frame, &event, msg);
X}
X
X/*
X * Pop up a message inside a textsw. Since textsw's don't really
X * popup (in SunOS 3.2), just display it and put up a 'done' button
X * to kill it when the user is done.
X * Frame should be the frame in which Event occured. Msg can
X * contain imbedded newlines.
X */
popup_msg(frame, event, msg)
XFrame *frame;
XEvent *event;
char *msg;
X{
X int lines = count_lines(msg);
X if (popup_frame != NULL) {
X /* Can only do one of these at a time. */
X return;
X }
X init_popup_msg(frame, msg, lines);
X textsw_insert(popup_text, msg, strlen(msg));
X window_set(popup_frame, WIN_X, event_x(event),
X WIN_Y, event_y(event),
X WIN_SHOW, TRUE,
X 0);
X}
X
X/*
X * A helper proc to do all the work of window creation for message popups
X */
init_popup_msg(baseframe, msg, lines)
XFrame baseframe;
char *msg;
X{
X popup_frame = window_create(baseframe, FRAME,
X WIN_ERROR_MSG, "Can't create window.",
X 0);
X popup_panel = window_create(popup_frame, PANEL,
X /* WIN_BELOW, popup_text, */
X WIN_X, ATTR_COL(0), /* bug workaround, should not be necessary */
X 0);
X panel_create_item(popup_panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, panel_button_image(popup_panel, "Done", 4, NULL),
X PANEL_NOTIFY_PROC, popup_textsw_done,
X 0);
X window_fit(popup_panel);
X popup_text = window_create(popup_frame, TEXTSW,
X WIN_ERROR_MSG, "Can't create window.",
X WIN_ROWS, min(30, lines),
X WIN_COLUMNS, max_line(msg)+3,
X TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
X TEXTSW_CONTENTS, msg,
X TEXTSW_BROWSING, TRUE,
X TEXTSW_DISABLE_LOAD, TRUE,
X TEXTSW_DISABLE_CD, TRUE,
X 0);
X window_fit(popup_frame);
X}
X
void
timeout_proc()
X{
X int val = (int)panel_get_value(time_left_item);
X if (val > 0) {
X panel_set(time_left_item, PANEL_VALUE, val-1, 0);
X do_with_delay(timeout_proc, 1, 0);
X } else {
X panel_set(time_left_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_paint(panel, PANEL_CLEAR);
X do_the_lock();
X }
X}
X
X/* A helper for killing message popups. */
static void
popup_textsw_done()
X{
X window_set(popup_frame, FRAME_NO_CONFIRM, TRUE, 0);
X window_destroy(popup_frame);
X popup_frame = NULL;
X panel_set(time_left_item, PANEL_SHOW_ITEM, TRUE, PANEL_VALUE, 10, 0);
X do_with_delay(timeout_proc, 1, 0);
X}
X
X/*
X * Find the size of the longest line in a string of lines separated by newlines
X */
max_line(s)
char *s;
X{
X int max = 0, count = 0;
X while (*s) {
X if (*s++ == '\n') {
X if (count > max)
X max = count;
X count = 0;
X continue;
X }
X count += 1;
X }
X if (count > max)
X max = count;
X return max;
X}
X
X/*
X * Count the number of lines in a string of lines separated by newlines.
X */
count_lines(s)
char *s;
X{
X int count = 0;
X while (*s) {
X if (*s++ == '\n')
X count += 1;
X }
X return count+1;
X}
X
X/* need functions, not macros, because of non-idempotent funcall arguments */
max(x,y)
X{
X return x<y ? y : x;
X}
X
min(x,y)
X{
X return x<y ? x : y;
X}
END_OF_FILE
if test 16203 -ne `wc -c <'src/glass.c'`; then
echo shar: \"'src/glass.c'\" unpacked with wrong size!
fi
# end of 'src/glass.c'
fi
echo shar: End of archive 7 \(of 10\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 10 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
More information about the Comp.sources.sun
mailing list