This is getbob.c in view mode; [Download] [Up]
/*
* getbob.c - Read RLE files onto hp bobcat screens.
*
* Author: Mark Bloomenthal
* Computer Science Dept.
* University of Utah
* Date: Fri Oct 17 1986
* Copyright (c) 1986, University of Utah
*
* Most code lifted from J W. Peterson.
*
* Flags are:
* -l Linear map
* -g gam Gammap map, use gamma of gam (floating point number)
* -d device Use the device specified.
* -x driver Use the driver specified.
* -p x y Position image lower left hand corner on the display. The
* x and y position is given in pixels with the origin taken as
* the lower left hand corner of the display. This flag is only
* useful with the -D, -d, and/or -x flags.
*
*/
#include "starbase.c.h"
#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include "rle.h"
#ifdef USE_STDLIB_H
#include <stdlib.h>
#else
#ifdef USE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef VOID_STAR
extern void *malloc();
#else
extern char *malloc();
#endif
extern void free();
#endif /* USE_STDLIB_H */
typedef char * string; /* Character Strings. */
typedef int boolean; /* Logical vars or values. */
#define TRUE 1 /* Logical constants. */
#define FALSE 0
typedef float single;
#define MAX(i,j) ( (i) > (j) ? (i) : (j) )
/* Some starbase type definitions. */
typedef single starbase_color_type[3];
typedef unsigned char starbase_color_index_type;
#define RASTERSIZE_LIM 1023
/* Standard color map offset. */
#define COLMAP_OFFSET 8
/* Color modes. */
#define MONOCHROME_MODE 1
#define EIGHT_BIT_COLOR_MODE 2
/* Scanline storage & RLE row pointers */
unsigned char scanline[4][RASTERSIZE_LIM], *rows[4];
/* Scanline to be written to device. */
starbase_color_index_type dest_pixels[RASTERSIZE_LIM]; /* avoid bludging stack */
/* Dither matrix. */
int dm16[16][16];
/* Tables for quantization. */
int errN[256], divN[256];
/* The gamma map and default gamma. */
int gammamap[256];
float gam = 2.0;
/* Input filename. */
string infname = NULL;
/* Color map flags. */
boolean linear_flag = FALSE;
boolean gamma_flag = FALSE;
boolean dummy;
/* The default device and device driver. */
string display_name = "/dev/graphics";
string driver_name = "hp98710";
/* For positioning the image on the display. */
boolean pos_flag;
int pic_x = 0;
int pic_y = 0;
/* How many bits in the devices color map. */
int dev_color_map_size;
/* What mode to dither into. Either 8 bit color or monochrome. */
int put_mode;
/* Color map to be written to device. */
int n_colmap_colors;
static starbase_color_type colmap[216];
/* The color to be used in case we do monochrome. */
float r_base_color = 1.0;
float g_base_color = 1.0;
float b_base_color = 1.0;
/* Starbase file descriptor for device where the picture goes. */
int picture_fd;
/*
* 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
};
static unsigned int
log_array[] = { 0, 4, 9, 13, 17, 21, 25, 29, 32, 36, 39, 42, 45, 48,
51, 54, 57, 59, 62, 64, 67, 69, 72, 74, 76, 78, 81,
83, 85, 87, 89, 91, 92, 94, 96, 98, 100, 101, 103, 105, 106,
108, 110, 111, 113, 114, 116, 117, 119, 120, 121, 123, 124,
125, 127, 128, 129, 131, 132, 133, 134, 136, 137, 138, 139,
140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174,
175, 175, 176, 177, 178, 179, 179, 180, 181, 182, 182, 183,
184, 185, 185, 186, 187, 187, 188, 189, 190, 190, 191, 192,
192, 194, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199,
200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 207,
207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 213,
214, 214, 215, 215, 216, 216, 217, 217, 218, 219, 219, 220,
220, 221, 221, 222, 222, 223, 223, 224, 224, 224, 225, 225,
226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231,
231, 232, 232, 233, 233, 234, 234, 235, 235, 235, 236, 236,
237, 237, 238, 238, 238, 239, 239, 240, 240, 240, 241, 241,
242, 242, 242, 243, 243, 244, 244, 244, 245, 245, 246, 246,
246, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 251,
251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 255 };
main( argc, argv)
{
int i;
int row;
boolean bw_flag = FALSE;
/* sbrk( 1000000 ); */
/* Get command line arguments. */
if ( scanargs( argc, argv,
"getbob l%- g%-gamma!f p%-pos!d!d d%-display!s x%-driver!s file%s",
&linear_flag, &gamma_flag, &gam,
&pos_flag, &pic_x, &pic_y,
&dummy, &display_name,
&dummy, &driver_name,
&infname ) == 0 )
exit( 1 );
/* Open file for reading, if no filename was specified, we'll read
* from stdin.
*/
rle_dflt_hdr.rle_file = rle_open_f("getbob", infname, "r");
/* Read header information from rle file. */
if ( rle_get_setup( &rle_dflt_hdr ) < 0 )
{
fprintf( stderr, "Error reading setup information from %s\n",
infname ? infname : "stdin" );
exit( 1 );
}
RLE_CLR_BIT( rle_dflt_hdr, RLE_ALPHA ); /* No alpha channel */
/* Set up gamma correction tables if need be. */
init_gamma_map();
direct_setup();
/* Set up rows to point to our copy of the scanline */
for ( i= 0; i < 4; i++ )
rows[i] = scanline[i];
/* Get the scanlines. */
for (i = rle_dflt_hdr.ymin; i < rle_dflt_hdr.ymax; i++)
{
rle_getrow( &rle_dflt_hdr, rows );
if ( put_mode == MONOCHROME_MODE )
put_line_mono( i );
else
put_line_8( i );
}
}
/*****************************************************************
* TAG( init_gamma_map )
*
* Compute a gamma correction map.
*/
init_gamma_map()
{
int i;
/* Compute a gamma correction map. */
for ( i = 0; i < 256; i++ )
{
if ( ! linear_flag )
{
gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gam ));
}
}
}
/*****************************************************************
* TAG( init_8_bit_color_map )
*
* Initialize the 8 bit color map.
*/
init_8_bit_color_map()
{
int i, j, k, l;
float magicfact;
/*
* Set up the color map entries. We will use 216 colors.
*/
n_colmap_colors = 216; /* Fill out the global. */
for ( i = 0; i < n_colmap_colors; i++ )
{
colmap[i][0] = ((i%6) * 51) / 255.0;
colmap[i][1] = (((i/6)%6) * 51) / 255.0;
colmap[i][2] = (((i/36)%6) * 51) / 255.0;
}
/* Compute tables */
for ( i = 0; i < 256; i++ )
{
/* Quantization table. */
divN[i] = i / 51;
/* Quantization error table. */
errN[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 );
}
/*****************************************************************
* TAG( init_monochrome_color_map )
*
* Initialize the monochrome color map. This is for devices with
* color maps too small to do good color dithering. The argument
* ncolors is the number of colors of the devices color map that
* may be used for dithering.
*/
init_monochrome_color_map( ncolors )
int ncolors;
{
int i, j, k, l;
float magicfact;
int color_val;
int k_val;
int err_interval;
/* Set up the color map entries into a single grayscale ramp. */
n_colmap_colors = ncolors; /* Fill out the global. */
for ( k = 0; k < ncolors; k++ )
{
color_val = (k * 255) / (ncolors - 1);
colmap[k][0] = (color_val * r_base_color) / 255.;
colmap[k][1] = (color_val * g_base_color) / 255.;
colmap[k][2] = (color_val * b_base_color) / 255.;
}
/* Compute tables for quantization. */
for ( i = 0; i < 256; i++ )
{
/* Compute the quantized index. */
k_val = ( i * (ncolors - 1) ) / 255;
divN[i] = k_val;
/* The error is the difference between the original color value and
* the value of the color map that the original color is quantized to.
*/
color_val = (k_val * 255) / (ncolors - 1); /* Quantized to this. */
errN[i] = i - color_val;
}
/* The interval between succesive colors in the color map is no less
* than this.
*/
err_interval = 255 / (ncolors - 1);
/*
* 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 255/(ncolors-1) sublevels).
*
* magicfact is (err_interval - 1)/16 so that we get numbers in the matrix
* from 0 to (err_interval - 1): errN gives numbers in 0 to err_interval,
* we want some chance that the number is greater than a matrix entry, so
* the highest matrix entry must be (err_interval - 1).
*/
magicfact = (float)(err_interval - 1) / 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 );
}
#define DMAP(v,x,y) (errN[v]>dm16[x][y] ? divN[v] + 1 : divN[v])
/*****************************************************************
* TAG( put_line_8 )
*
* Map a 24 bit scanline to 8 bits through the dither matrix.
*/
put_line_8( y )
int y;
{
register unsigned char *r, *g, *b;
register int i, dither_col, dither_row;
register starbase_color_index_type *dest_pixel_ptr;
int xmax = rle_dflt_hdr.xmax;
int g_offset, b_offset;
/* In case we have less than 3 color channels. */
for (i = 2; i >= rle_dflt_hdr.ncolors; i--)
bcopy(rows[0], rows[i], rle_dflt_hdr.xmax - rle_dflt_hdr.xmin);
dither_row = y % 16;
dither_col = 0;
r = rows[0];
g = rows[1];
b = rows[2];
dest_pixel_ptr = &dest_pixels[0];
/* Linear map. */
if ( linear_flag )
for ( i = 0; i < xmax; i++, r++, g++, b++,
dither_col = ((dither_col + 1) & 15),
dest_pixel_ptr++ )
*dest_pixel_ptr =
DMAP( *r, dither_col, dither_row ) +
DMAP( *g, dither_col, dither_row ) * 6 +
DMAP( *b, dither_col, dither_row ) * 36 +
COLMAP_OFFSET;
/* RLE file with color map. */
else if ( rle_dflt_hdr.ncmap )
{
/* Compute offsets to the green and blue sections of the color map. */
g_offset = 1 << rle_dflt_hdr.cmaplen;
b_offset = 2 * g_offset;
for ( i = 0; i < xmax; i++, r++, g++, b++,
dither_col = ((dither_col + 1) & 15),
dest_pixel_ptr++ )
*dest_pixel_ptr =
DMAP( rle_dflt_hdr.cmap[*r], dither_col, dither_row ) +
DMAP( rle_dflt_hdr.cmap[*g + g_offset],
dither_col, dither_row ) * 6 +
DMAP( rle_dflt_hdr.cmap[*b + b_offset],
dither_col, dither_row ) * 36 +
COLMAP_OFFSET;
}
/* Gamma correction is the default. */
else
for ( i = 0; i < xmax; i++, r++, g++, b++,
dither_col = ((dither_col + 1) & 15),
dest_pixel_ptr++ )
*dest_pixel_ptr =
DMAP( gammamap[*r], dither_col, dither_row ) +
DMAP( gammamap[*g], dither_col, dither_row ) * 6 +
DMAP( gammamap[*b], dither_col, dither_row ) * 36 +
COLMAP_OFFSET;
/* Write this scanline to the device. */
write_scanline( y );
}
/*****************************************************************
* TAG( put_line_mono )
*
* For small color maps. Dither into monochrome.
*/
put_line_mono( y )
int y;
{
register unsigned char *r, *g, *b;
register int i, dither_col, dither_row;
register starbase_color_index_type *dest_pixel_ptr;
int xmax = rle_dflt_hdr.xmax;
int bw_val;
int g_offset, b_offset;
/* In case we have less than 3 color channels. */
for (i = 2; i >= rle_dflt_hdr.ncolors; i--)
bcopy(rows[0], rows[i], rle_dflt_hdr.xmax - rle_dflt_hdr.xmin);
dither_row = y % 16;
dither_col = 0;
r = rows[0];
g = rows[1];
b = rows[2];
dest_pixel_ptr = &dest_pixels[0];
/* Linear map. */
if ( linear_flag )
for ( i = 0; i < xmax; i++, r++, g++, b++,
dither_col = ((dither_col + 1) & 15),
dest_pixel_ptr++ )
{
bw_val =
(35*(*r) + 55*(*g) + 10*(*b)) / 100;
*dest_pixel_ptr =
DMAP( bw_val, dither_col, dither_row ) + COLMAP_OFFSET;
}
/* RLE file with color map. */
else if ( rle_dflt_hdr.ncmap )
{
/* Compute offsets to the green and blue sections of the color map. */
g_offset = 1 << rle_dflt_hdr.cmaplen;
b_offset = 2 * g_offset;
for ( i = 0; i < xmax; i++, r++, g++, b++,
dither_col = ((dither_col + 1) & 15),
dest_pixel_ptr++ )
{
bw_val =
( 35 * rle_dflt_hdr.cmap[*r] +
55 * rle_dflt_hdr.cmap[*g + g_offset] +
10 * rle_dflt_hdr.cmap[*b + b_offset] ) / 100;
*dest_pixel_ptr =
DMAP( bw_val, dither_col, dither_row ) + COLMAP_OFFSET;
}
}
/* Gamma correction is the default. */
else
for ( i = 0; i < xmax; i++, r++, g++, b++,
dither_col = ((dither_col + 1) & 15),
dest_pixel_ptr++ )
{
bw_val =
(35*gammamap[*r] + 55*gammamap[*g] + 10*gammamap[*b]) / 100;
*dest_pixel_ptr =
DMAP( bw_val, dither_col, dither_row ) + COLMAP_OFFSET;
}
/* Write this scanline to the device. */
write_scanline( y );
}
/*****************************************************************
* TAG( direct_setup )
*
* Use starbase to talk directly to graphics device.
*/
direct_setup()
{
single p_lim[2][3], res[3], p1[3], p2[3];
int map_size;
int dev_xmax, dev_ymax;
picture_fd = gopen( display_name, OUTDEV, driver_name, 0 );
if ( picture_fd < 0 )
{
fprintf( stderr, "Can't open device.\n" );
exit( 1 );
}
/* Find out info about this device. */
inquire_sizes( picture_fd, p_lim, res, p1, p2, &map_size );
if ( map_size >= 256 )
{
put_mode = EIGHT_BIT_COLOR_MODE;
init_8_bit_color_map();
}
else
{
put_mode = MONOCHROME_MODE;
init_monochrome_color_map( map_size - COLMAP_OFFSET );
}
write_color_map( picture_fd );
/* Set the screen limits in pixels so we can use starbase in a device
* independent way.
*
* It is assumed that the p_lim values returned by inquire_sizes are the
* lower left screen coordinates in (float) pixels and the upper right
* screen coordinates in (float) pixels. It is also assumed that the
* range of values in x and y coordinates are given from 0 to some
* positive maximum value.
*/
dev_xmax = MAX( p_lim[0][0], p_lim[1][0] );
dev_ymax = MAX( p_lim[0][1], p_lim[1][1] );
if ( rle_dflt_hdr.xmax > dev_xmax )
rle_dflt_hdr.xmax = dev_xmax;
if ( rle_dflt_hdr.ymax > dev_ymax )
rle_dflt_hdr.ymax = dev_ymax;
/* Make sure that the specified lower left hand corner of the image
* will keep the image in bounds.
*/
if ( ( rle_dflt_hdr.xmax + pic_x ) > dev_xmax )
pic_x = dev_xmax - rle_dflt_hdr.xmax;
if ( ( rle_dflt_hdr.ymax + pic_y ) > dev_ymax )
pic_y = dev_ymax - rle_dflt_hdr.ymax;
/* Set to use the whole display surface. */
mapping_mode( picture_fd, DISTORT );
/* Set to address the pixels in a device independent way. */
vdc_extent( picture_fd, 0.0, 0.0, 0.0,
(single)dev_xmax, (single)dev_ymax, 0.0 );
clip_rectangle( picture_fd, 0.0, (single)dev_xmax, 0.0, (single)dev_ymax );
}
/*****************************************************************
* TAG( write_color_map )
*
* Write color map to device.
*
*/
write_color_map( star_fd )
int star_fd;
{
define_color_table( star_fd, COLMAP_OFFSET, n_colmap_colors, colmap );
}
/*****************************************************************
* TAG( write_scanline )
*
* Write scanline to device.
*
*/
write_scanline( y )
int y;
{
block_write( picture_fd,
(single)(rle_dflt_hdr.xmin + pic_x), (single)(y + pic_y),
rle_dflt_hdr.xmax - rle_dflt_hdr.xmin, 1,
dest_pixels, FALSE );
}
/*****************************************************************
* TAG( bcopy )
*
* Move contents of a block to a new location.
* For systems without a bcopy system routine.
*/
void bcopy( src_ptr, dst_ptr, size )
register int * src_ptr, * dst_ptr;
int size;
{
register int words;
register char * byte_src_ptr, * byte_dst_ptr;
register int bytes;
/* Tight word copy loop for most or all of the block. */
words=size/sizeof(int);
bytes = size - words*sizeof(int);
while ( words-- )
*dst_ptr++ = *src_ptr++;
/* Tight byte copy loop for the remainder. */
byte_src_ptr = (char *)src_ptr;
byte_dst_ptr = (char *)dst_ptr;
while ( bytes-- )
*byte_dst_ptr++ = *byte_src_ptr++;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.