ftp.nice.ch/pub/next/unix/graphics/urt.3.0.s.tar.gz#/urt.3.0.s/get/getap.c

This is getap.c in view mode; [Download] [Up]

/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is 
 * preserved on all copies.
 * 
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the 
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/* 
 * getfb.c - Read RLE files onto apollo screens.
 * 
 * Author:	John W. Peterson
 * 		Computer Science Dept.
 * 		University of Utah
 * Date:	Fri Jun 27 1986
 * Copyright (c) 1986 John W. Peterson
 *
 * Revision 1.1  87/05/26  13:22:30  Clark
 * Add window name overhead to create window call and fix y calculation in
 * put_line.
 * Revision 1.2  87/10/01  10:38:00  Clark
 * Add code to wait for user input, quit when user types "q"
 * and to screen dump a GMR bitmap file if user types "d"
 * Revision 1.3  88/01/07  08:28:30  Clark
 * Add code to put file name in window legend and fix for obscured
 * window, add flag for no border and x,y position
 * Revision 1.4  88/01/08  08:10:30  Clark
 * Add code for adding text to image
 * Revision 1.5  88/02/25  01:54:00  Clark
 * Re-instate BW code, and add suport for 4 bit plane workstations.
 * Revision 1.6  88/02/29  11:33:50  Clark
 * Use all available bit planes for gray scale. Use 16x16 dither
 * for BW nodes instead of 8x8 S. Kitaoka Grey table
 *
 *
 * Some code lifted from an old getX by Spencer Thomas and showbw
 * by Jim Schimpf.
 *
 * Flags are:
 *   -l		Linear map
 *   -g gam	Gammap map, use gamma of gam (floating point number)
 *   -b		Use full 24 bit mode (DN550, DN560, DN660 only)
 *   -w         Black and white
 *   -r		Flip white on black/black on white for grayscale display.
 *   -x left	X coordinate of window
 *   -y top	Y coordinate of window
 *   -t text	Add text to bottom of image
 *   -n 	No border or legend
 *
 * NOTE: This version applies the color map if present.
 */

#include <stdio.h>
#include <math.h>
#include "rle.h"
#ifdef USE_STDLIB_H
#include <stdlib.h>
#endif

#include "/sys/ins/base.ins.c"
#include "/sys/ins/gpr.ins.c"
#include "/sys/ins/error.ins.c"
#include "/sys/ins/pad.ins.c"

#define RASTERSIZE 1023
#define COLMAP_OFFSET 16

#define sysdebug if ((status.all)!=0) error_$print(status)

/* Scanline storage & RLE row pointers */
rle_pixel **rows;
int dm16[16][16];
int mod51[256], div51[256];
int mod255[256], div255[256];
int modN[256], divN[256];
float gam = 2.0;		/* Default gamma */
int inverse_flag = false;	/* If true, swap bits on B&W displays */
int gray_flag = false;		/* True if making BW image on color screen */
int borrow_mode = false;	/* DN560/660 imaging mode (borrow screen)) */
int 
    linear_flag = false,	/* Color map flags */
    gam_flag = true;
int four_flag = false;		/* If true, workstation has only 4 planes */
int bw_flag = false;		/* If true, workstation is BW */
int x_flag = false;		/* True if X coord specified */ 
int y_flag = false;		/* True if Y coord specified */ 
int no_border_flag = false;     /* True if no border or legend */
int left = 0;			/* Default window X coord */
int top = 0;			/* Default window Y coord */
gpr_$pixel_value_t dest_pixels[RASTERSIZE];  /* avoid bludging stack */
gpr_$offset_t size;
short font_id;
short middle;
status_$t status;
gpr_$keyset_t keyset = { 4294967295, 4294967295, 4294967295, 4294967295, 
                         4294967295, 4294967295, 4294967295, 4294967295 };
char key;
gpr_$position_t position;
boolean obs;
gpr_$event_t event;
gpr_$version_t version;
gpr_$offset_t dump_size;
gpr_$window_t dump_window;
gpr_$attribute_desc_t attribs;
gpr_$bitmap_desc_t bitmap;
gpr_$bitmap_desc_t dump_bitmap;
boolean created;
gpr_$bmf_group_header_array_t header;
gpr_$color_vector_t color_map;
short map[3][256];

/*
 * Basic magic square for dithering
 */
int magic[4][4] =  {
 	 0, 14,  3, 13,
	11,  5,  8,  6,
	12,  2, 15,  1,
	 7,  9,  4, 10
};

main(argc, argv)
int argc;
char **argv;
{
    int i;
    short len;
    int row;
    unsigned n;
    char * fname = NULL;
    char * text = NULL;
    int text_flag = 0;
    short namelen, tok_count;
    char gstring[20];

    set_sbrk_size( 1000000 );

    if (! scanargs( argc, argv,
		   "% b%- l%- r%- w%- n%- g%-gamma!f x%-left!d y%-top!d t%-text!s file%s",
		   &borrow_mode, &linear_flag, &inverse_flag,
		   &gray_flag, &no_border_flag, &gam_flag, &gam,
		   &x_flag, &left, &y_flag, &top, &text_flag, &text, &fname ))          
	exit( 1 );
    rle_dflt_hdr.rle_file = rle_open_f("getap", fname, "r");

    switch( (int) rle_get_setup( &rle_dflt_hdr ) )
    {
    case 0:
	break;			/* successful open */
    case -1:			/* not an RLE file */
    case -4:			/* or header is short */
	fprintf( stderr, "getap: %s is not an RLE file\n", fname );
	exit(-4);
	break;
    case -2:
	fprintf( stderr, "getap: malloc failed\n" );
	exit(-2);
	break;
    case -3:
	fprintf( stderr, "getap: input file is empty\n" );
	exit(-3);
	break;
    }

/*    RLE_CLR_BIT( rle_dflt_hdr, RLE_ALPHA );	/* No alpha channel */

    rle_row_alloc( &rle_dflt_hdr, &rows );

    if (borrow_mode)
    {
	borrow_setup();
	borrow_color_map(); 
	if (rle_dflt_hdr.ymax > 511)
	    rle_dflt_hdr.ymax = 511;
    }
    else
    {
	setup_scr(rle_dflt_hdr.xmax, rle_dflt_hdr.ymax);
	window_color_map();
	if (rle_dflt_hdr.ymax > RASTERSIZE)
	    rle_dflt_hdr.ymax = RASTERSIZE;
    }

    if (bw_flag) gray_flag = true;

    for (i = rle_dflt_hdr.ymin; i <= rle_dflt_hdr.ymax; i++)
    {
	rle_getrow( &rle_dflt_hdr, rows );
	if (borrow_mode)
	    put_line_borrow(i);
	else
	{
	    if (gray_flag)
		put_linebw(i);
	    else
	    {
		if (four_flag)
		    put_line4(i);
		else
		    put_line8(i);
	    }
	}
    }
    if (text_flag)
    {
	if (!borrow_mode) gpr_$acquire_display( status ) ;
	gpr_$load_font_file( "nonie.r.16", (short) 10, font_id, status );
	gpr_$set_text_font( font_id, status );
	gpr_$set_text_background_value( (int) -1, status );
	gpr_$set_text_value( (int) 17, status );
	gpr_$inq_text_extent( *text, (short) strlen(text),
			      size, status );
	middle = (rle_dflt_hdr.xmax/2) - (size.x_size/2);
	if (middle < 0) middle=0;
	gpr_$move( middle, (short)(rle_dflt_hdr.ymax-15), status);
	gpr_$text( *text, (short) strlen(text), status);
	if (!borrow_mode) gpr_$release_display( status ) ;
    }
    do
    {
	if (!borrow_mode) gpr_$acquire_display( status ) ;
	gpr_$enable_input( gpr_$keystroke, keyset, status ) ;
	obs = gpr_$event_wait ( event, key, position, status ) ;
	if (!borrow_mode) gpr_$release_display( status ) ;
	if ( (event == gpr_$keystroke) && ( (key == 'd') || (key == 'D') ) )
	{
	    if (borrow_mode)
	    {
		gpr_$inq_bitmap( bitmap, status ) ;
		sysdebug;
		gpr_$allocate_attribute_block(attribs,status);
		sysdebug;
		header[0].n_sects	= 8;
		header[0].pixel_size     = 1;
		header[0].allocated_size = 0;
		header[0].bytes_per_line = 0;
		header[0].bytes_per_sect = 0;
		dump_size.x_size = 1024;
		dump_size.y_size = 1024;
		gpr_$open_bitmap_file(gpr_$create,"screen_dump",(short)11,version,
		    dump_size,(short)1,header,attribs,dump_bitmap,created,status);
		if (status.all == 0)
		{
		    gpr_$set_bitmap(dump_bitmap,status);
		    sysdebug;
		    gpr_$inq_color_map((int)0,256,color_map,status);
		    sysdebug;
		    gpr_$set_bitmap_file_color_map(dump_bitmap,0,256,color_map,status);
		    sysdebug;
		    dump_window.window_base.x_coord = 0;
		    dump_window.window_base.y_coord = 0;
		    dump_window.window_size.x_size = 1024;
		    dump_window.window_size.y_size = 1024;
		    gpr_$set_imaging_format(gpr_$interactive, status );
		    sysdebug;
		    gpr_$pixel_blt(bitmap,dump_window,dump_window.window_base,status);
		    sysdebug;
		    gpr_$set_imaging_format(gpr_$imaging_512x512x24, status );
		    sysdebug;
		}
		else
		{
		    fprintf(stderr, "getap: Could not open bitmap file screen_dump - ");
		    error_$print(status);
		}
	    }
	    else
	    {   
		pad_$dm_cmd ((short)1, "CPO /COM/CPSCR SCREEN_DUMP -GPR", (short)31, status ) ;
		sysdebug;
	    }
	}
	if ( (event == gpr_$keystroke) && ( (key == 'p') || (key == 'P') && (!borrow_mode) ) )
	{
	    pad_$dm_cmd ((short)1, "WP", (short)2, status ) ;
	    sysdebug;
	}
    }
    while ( !( (event == gpr_$keystroke) && ( (key == 'q') || (key == 'Q') ) ) );
    if (borrow_mode)
    {
	gpr_$set_imaging_format(gpr_$interactive, status );
	sysdebug;
    }
    if (!borrow_mode && four_flag)
    {
	gpr_$acquire_display( status ) ;
	gpr_$set_color_map((int)0,8,color_map,status);
	gpr_$release_display( status ) ;
    }
}

/*
 * Initialize the GPR package to imaging mode
 */
borrow_setup()
{
    gpr_$offset_t size;
    gpr_$bitmap_desc_t main_bitmap;      /* Master bitmap */

    size.x_size = 1024;
    size.y_size = 1024;			/* GPR will shrink to fit */

    gpr_$init(gpr_$borrow, 1, size, 7, main_bitmap, status );
    sysdebug;

    gpr_$set_imaging_format( gpr_$imaging_512x512x24, status );
    sysdebug;
    if (status.all != status_$ok)
    {
	fprintf(stderr, "getap: Wrong hardware?\n");
	exit(-1);
    }
}

/* Set up the color map (imaging mode) */
borrow_color_map()
{
    unsigned int value;
    unsigned int intgam;
    int i, map_offset;
    gpr_$color_vector_t colmap;
    
    if ( rle_dflt_hdr.ncmap )	/* Must read color map */
    {
	map_offset = 1 << rle_dflt_hdr.cmaplen;

	/* This needs more thought; handle ncmap = 1, etc. */
	if (rle_dflt_hdr.ncmap == 3)

	for (i=0; i < 256; i++)
	{
            /* This is bogus, we need to index cmap!... */
	    
	    value = (((rle_dflt_hdr.cmap[i]>> 8) & 0xFF) << 16);
	    value |= (((rle_dflt_hdr.cmap[i+map_offset] >> 8) & 0xFF) << 8);
	    value |= ((rle_dflt_hdr.cmap[i+2*map_offset] >> 8) & 0xFF);
	    colmap[i] = value;
	}
    }
    else
    {	  
	if (gam_flag)
	{
	    for (i = 0; i < 256; i++)
	    {
		intgam = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gam ));
		value = intgam;
		value |= (intgam << 8);
		value |= (intgam << 16);
		colmap[i] = value;
	    }
	}
	else
	{			/* Default is linear map */
	    for (i=0; i < 256; i++)
	    {
		value = (i << 16);
		value |= (i << 8); 
		value |= i;
		colmap[i] = value;
	    }
	}
    }
	    
	  
    gpr_$set_color_map( (int) 0, 256, colmap, status );
    sysdebug;
}

/*
 * Initialize the 8 bit color map.  Use gamma corrected map.
 */
window_color_map()
{
    int i, j, k, l, planes, map_offset;
    unsigned int value;
    unsigned int intgam;
    float magicfact;
    status_$t status;
    static gpr_$color_vector_t colmap;
    gpr_$display_config_t config;

    if ( rle_dflt_hdr.ncmap )	/* Must read color map */
    {
	map_offset = 1 << rle_dflt_hdr.cmaplen;

	/* This needs more thought; handle ncmap = 1, etc. */
	if (rle_dflt_hdr.ncmap == 3)

	for (i=0; i < 256; i++)
	{
            /* This is bogus, we need to index cmap!... */
	    
	    map[0][i] = ((rle_dflt_hdr.cmap[i]>> 8) & 0xFF);
	    map[1][i] = ((rle_dflt_hdr.cmap[i+map_offset] >> 8) & 0xFF);
	    map[2][i] = ((rle_dflt_hdr.cmap[i+2*map_offset] >> 8) & 0xFF);
	}
    }
    else
    {	  
	if (gam_flag)
	{
	    for (i = 0; i < 256; i++)
	    {
		intgam = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gam ));
		map[0][i] = intgam;
		map[1][i] = intgam;
		map[2][i] = intgam;
	    }
	}
	else
	{			/* Default is linear map */
	    for (i=0; i < 256; i++)
	    {
		map[0][i] = i;
		map[1][i] = i;
		map[2][i] = i;
	    }
	}
    }

    gpr_$inq_config( config, status );
    if ((config == gpr_$color_1024x1024x4) ||
	(config == gpr_$color_1024x800x4) ||
	(config == gpr_$color2_1024x800x4)) four_flag = true;
    if ((config == gpr_$bw_800x1024) ||
	(config == gpr_$bw_1024x800) ||
	(config == gpr_$bw_1280x1024)) bw_flag = true;

    if (four_flag && !bw_flag && !gray_flag)    
    {
	/* 
	 * Set up the 4-bit color map entries.
	 */
	for(i = 0; i < 8; i++) {
	    colmap[i] = ((i%2) * 255) << 16;
	    colmap[i] |= (((i/2)%2) * 255) << 8;
	    colmap[i] |= (((i/4)%2) * 255);
	}

	/* Save DM window colors */
	gpr_$acquire_display( status );
	gpr_$inq_color_map((int)0,8,color_map,status);
	gpr_$set_color_map( (int)0, 8, colmap, status );
	gpr_$release_display( status );

	/* Compute tables */
	for ( i = 0; i < 256; i++ )
	{
	    mod255[i] = i % 255;
	    div255[i] = i / 255;
	}

	/*
	 * Expand 4x4 dither pattern to 16x16.  4x4 leaves obvious patterning,
	 * and doesn't give us full intensity range (only 17 sublevels,
	 * we want at least 51).  Note that 8x8 would be sufficient, but
	 * 16x16 is easier to build.
	 * 
	 * magicfact is 253/16 so that we get numbers in the matrix from 0 to
	 * 253: mod 255 gives numbers in 0 to 254, we want some chance that the
	 * number is greater than a matrix entry, so the highest matrix
	 * entry must be 253.
	 */
	magicfact = 253. / 16.;
	for ( i = 0; i < 4; i++ )
	    for ( j = 0; j < 4; j++ )
	        for ( k = 0; k < 4; k++ )
		    for ( l = 0; l < 4; l++ )
		        dm16[4*k+i][4*l+j] = (int)(0.5 + magic[i][j]
					           * magicfact
					           + (magic[k][l] / 16.)
					           * magicfact);
    }
    else if (four_flag && !bw_flag && gray_flag)
    {
        bwdithermap( 8, gam, colmap, divN, modN, dm16);

	for(i = 0; i < 8; i++) {
            j = colmap[i];
	    colmap[i] = j << 16;
	    colmap[i] |= j << 8;
	    colmap[i] |= j;
	}
	/* Save DM window colors */
	gpr_$acquire_display( status );
	gpr_$inq_color_map((int)0,8,color_map,status);
	gpr_$set_color_map( (int)0, 8, colmap, status );
	gpr_$release_display( status );

    }
    else if (!bw_flag && !gray_flag)
    {
	/* 
	 * Set up the 8 bit color map entries.  We don't yet know the location
	 * in the map at which each will reside, so init it to 0.
	 */
	for(i = 0; i < 216; i++) {
	    colmap[i] = ((i%6) * 51) << 16;
	    colmap[i] |= (((i/6)%6) * 51) << 8;
	    colmap[i] |= (((i/36)%6) * 51);
	}

	/* Offset from DM window colors */
	gpr_$acquire_display( status );
	gpr_$set_color_map( (int) COLMAP_OFFSET, 256 - COLMAP_OFFSET,
        	           colmap, status );
	gpr_$release_display( status );

	/* Compute tables */
	for ( i = 0; i < 256; i++ )
	{
	    mod51[i] = i % 51;
	    div51[i] = i / 51;
	}

    /*
	 * Expand 4x4 dither pattern to 16x16.  4x4 leaves obvious patterning,
	 * and doesn't give us full intensity range (only 17 sublevels,
	 * we want at least 51).  Note that 8x8 would be sufficient, but
	 * 16x16 is easier to build.
	 * 
	 * magicfact is 49/16 so that we get numbers in the matrix from 0 to
	 * 49: mod 51 gives numbers in 0 to 50, we want some chance that the
	 * number is greater than a matrix entry, so the highest matrix
	 * entry must be 49.
	 */
	magicfact = 49. / 16.;
	for ( i = 0; i < 4; i++ )
	    for ( j = 0; j < 4; j++ )
	        for ( k = 0; k < 4; k++ )
		    for ( l = 0; l < 4; l++ )
		        dm16[4*k+i][4*l+j] = (int)(0.5 + magic[i][j]
					           * magicfact
					           + (magic[k][l] / 16.)
					           * magicfact);
    }
    else if (!bw_flag)
    {
        bwdithermap( 240, gam, colmap, divN, modN, dm16);

	for(i = 0; i < 240; i++) {
            j = colmap[i];
	    colmap[i] = j << 16;
	    colmap[i] |= j << 8;
	    colmap[i] |= j;
	}
	/* Offset from DM window colors */
	gpr_$acquire_display( status );
	gpr_$set_color_map( (int) COLMAP_OFFSET, 256 - COLMAP_OFFSET,
        	           colmap, status );
	gpr_$release_display( status );
    }
    else
    {
        bwdithermap( 2, gam, colmap, divN, modN, dm16);
    }
}

/* All the fun stuff to set up an apollo window */
setup_scr(hsize,vsize)
int hsize,vsize;
{
    gpr_$offset_t size;
    gpr_$color_vector_t colmap;
    gpr_$attribute_desc_t hidden_desc;
    unsigned int value;
    int i;
    name_$pname_t output_file;
    short len, w, h;
    pad_$window_desc_t window_shape;
    static gpr_$bitmap_desc_t main_bitmap;
    short fontid;
    static stream_$id_t out_stream;

    /* Open a separate window to display the results */

    window_shape.top = 0;
    window_shape.left = 0;
    if ( !no_border_flag )
    {
	w = 11;
	h = 34;
    }
    else
    {
	w = 1;
	h = 1;
    }
    window_shape.width = (short)hsize + w;
    window_shape.height = (short)vsize + h;

    pad_$create_window( "", (short) 0, pad_$transcript, (short) 1,
			window_shape, out_stream, status );

    if ( no_border_flag ) pad_$set_border( out_stream, (short) 1, false, status );

    window_shape.top = top;
    window_shape.left = left;
    pad_$set_full_window( out_stream, (short) 1, window_shape, status );

    pad_$set_auto_close( out_stream, (short) 1, true, status );

    size.x_size = 1024;  /* GPR will shrink to fit */
    size.y_size = 1024;

    /* Initialize the graphics primitives package */

    gpr_$init(gpr_$direct,
              out_stream,               /* "unit" */
              size,                     /* size of the initial bitmap */
              7,                        /* identifier of the heightest
                                           numbered bitmap plane */
              main_bitmap,              /* resulting bitmap descriptor */
              status);

    gpr_$set_auto_refresh( true, status );  /* all yours, DM. */

    gpr_$set_obscured_opt( gpr_$block_if_obs, status );

    gpr_$acquire_display( status ) ;

    /* set the new bitmap descriptor to be the 'current bitmap' */
    gpr_$set_bitmap(main_bitmap,status);
    gpr_$clear( gpr_$black, status );

    gpr_$release_display( status );
}

/* Write a scanline to the frame buffer using full 24 bit mode */
put_line_borrow(y)
int y;
{
    int i;
    gpr_$window_t dest_box;
    unsigned char *redptr, *grnptr, *bluptr;


    dest_box.window_base.x_coord = 0;
    dest_box.window_base.y_coord = 511 - y;
    dest_box.window_size.x_size = 511;
    dest_box.window_size.y_size = 1;

    redptr = rows[RLE_RED];
    if (rle_dflt_hdr.ncolors == 3)
    { 
        grnptr = rows[RLE_GREEN];
        bluptr = rows[RLE_BLUE];
    }
    else	/* If only one channel, get all from same one  */
    {
        grnptr = rows[0];
        bluptr = rows[0];
    }
    for (i = rle_dflt_hdr.xmin; i <= rle_dflt_hdr.xmax; i++)
    {
	dest_pixels[i] = (gpr_$pixel_value_t) ((*redptr) << 16);
	dest_pixels[i] |= (gpr_$pixel_value_t) ((*grnptr) << 8);
	dest_pixels[i] |= (gpr_$pixel_value_t) (*bluptr);
	redptr++;  grnptr++; bluptr++;
    }
    gpr_$write_pixels( dest_pixels, dest_box, status );
    sysdebug;
}

/*
 * Map a 24 bit scanline to 4 bits through the dither matrix.
 */
#define DMAP4(v,x,y)	(mod255[v]>dm16[x][y] ? div255[v] + 1 : div255[v])

put_line4( y )
int y;
{
    register unsigned char *r, *g, *b;
    register int i, col, row;
    gpr_$window_t dest_box;
    int n = rle_dflt_hdr.xmax;

    r = rows[RLE_RED];
    if (rle_dflt_hdr.ncolors == 3)
    { 
        g = rows[RLE_GREEN];
        b = rows[RLE_BLUE];
    }
    else
    {
        g = rows[0];
        b = rows[0];
    }

    for ( row = y % 16, col = 0, i = 0;
	 i <= n; i++, r++, g++, b++, col = ((col + 1) & 15) )
	dest_pixels[i] = DMAP4(map[0][*r], col, row) +
	    		 DMAP4(map[1][*g], col, row) * 2 +
			 DMAP4(map[2][*b], col, row) * 4;

    dest_box.window_base.x_coord = rle_dflt_hdr.xmin;
    dest_box.window_base.y_coord = rle_dflt_hdr.ymax - y;
    dest_box.window_size.x_size = rle_dflt_hdr.xmin + rle_dflt_hdr.xmax + 1;
    dest_box.window_size.y_size = 1;

    gpr_$acquire_display( status ) ;
    gpr_$write_pixels( dest_pixels, dest_box, status ); 
    gpr_$release_display( status );

}

/*
 * Map a 24 bit scanline to 8 bits through the dither matrix.
 */
#define DMAP8(v,x,y)	(mod51[v]>dm16[x][y] ? div51[v] + 1 : div51[v])

put_line8( y )
int y;
{
    register unsigned char *r, *g, *b;
    register int i, col, row;
    gpr_$window_t dest_box;
    int n = rle_dflt_hdr.xmax;

    r = rows[RLE_RED];
    if (rle_dflt_hdr.ncolors == 3)
    { 
        g = rows[RLE_GREEN];
        b = rows[RLE_BLUE];
    }
    else
    {
        g = rows[0];
        b = rows[0];
    }

    for ( row = y % 16, col = 0, i = 0;
	 i <= n; i++, r++, g++, b++, col = ((col + 1) & 15) )
	dest_pixels[i] = DMAP8(map[0][*r], col, row) +
	    		 DMAP8(map[1][*g], col, row) * 6 +
			 DMAP8(map[2][*b], col, row) * 36 + COLMAP_OFFSET;

    dest_box.window_base.x_coord = rle_dflt_hdr.xmin;
    dest_box.window_base.y_coord = rle_dflt_hdr.ymax - y;
    dest_box.window_size.x_size = rle_dflt_hdr.xmin + rle_dflt_hdr.xmax + 1;
    dest_box.window_size.y_size = 1;

    gpr_$acquire_display( status ) ;
    gpr_$write_pixels( dest_pixels, dest_box, status ); 
    gpr_$release_display( status );

}

/*
 * Map a 24 bit scanline through to get dithered black and white
 */
#define DMAP(v,x,y)	(modN[v]>dm16[x][y] ? divN[v] + 1 : divN[v])

put_linebw( y )
int y;
{
    register unsigned char *r, *g, *b;
    register int i, col, row;
    gpr_$window_t dest_box;
    int pixel;
    int n = rle_dflt_hdr.xmax;
    gpr_$pixel_value_t B = 0, W = 1;

    r = rows[RLE_RED];
    if (rle_dflt_hdr.ncolors == 3)
    { 
        g = rows[RLE_GREEN];
        b = rows[RLE_BLUE];
    }
    else
    {
        g = rows[0];
        b = rows[0];
    }

    if (bw_flag)
    {
        if (inverse_flag)
        {
	    B = 1; W = 0;		/* Swap meaning of Black and White */
        }

        for ( row = y % 16, col = 0, i = 0;
	     i <= n; i++, r++, g++, b++, col = ((col + 1) & 15) )
        {
	    /* Convert to BW (uses YIQ/percentage xformation) */
	    pixel = (35*map[0][*r] + 55*map[1][*g] + 10*map[2][*b]) / 100;
	    if (pixel < 0) pixel += 256;
	    dest_pixels[i] = ((DMAP(pixel, col, row) > 0) ? W : B);
	}
    }
    else
    {
        for ( row = y % 16, col = 0, i = 0;
	     i <= n; i++, r++, g++, b++, col = ((col + 1) & 15) )
        {
	    /* Convert to BW (uses YIQ/percentage xformation) */
	    pixel = (35*map[0][*r] + 55*map[1][*g] + 10*map[2][*b]) / 100;
	    if (pixel < 0) pixel += 256;
	    if (inverse_flag)
            {
	        pixel = ((~pixel) & 0xFF);		/* Swap meaning of Black and White */
            }
            if (four_flag)
            {
	        dest_pixels[i] = DMAP(pixel, col, row);
            }
            else
            {
		dest_pixels[i] = DMAP(pixel, col, row) + COLMAP_OFFSET;
	    }
	}
    }
    dest_box.window_base.x_coord = rle_dflt_hdr.xmin;
    dest_box.window_base.y_coord = rle_dflt_hdr.ymax - y;
    dest_box.window_size.x_size = rle_dflt_hdr.xmin + rle_dflt_hdr.xmax + 1;
    dest_box.window_size.y_size = 1;

    gpr_$acquire_display( status ) ;
    gpr_$write_pixels( dest_pixels, dest_box, status ); 
    gpr_$release_display( status );

}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.