[net.sources] Oops, repost

hutch@sdcsvax.UUCP (Jim Hutchison) (04/20/86)

<someone elses bug strikes here.>

I was extremely foolish, and put in a change to the code as I was
posting it.  Now I know better, but you need to know to.  The
effect of this bug is to make the dither never happen.  I changed
a division to a shift...and then hit :wq

My sincerest apologys to anyone this disturbed.

/* Below is the revised code */

#include <stdio.h>
#include <sys/file.h>
#include <pixrect/pixrect_hs.h>

/*
 *	Dither!  Color dither a U.S.C. tape image.
 *
 *	Original Tape code by Brian Kantor (brian@UCSD).
 *
 *	The dithering is the product of madness and extrapolation
 *	from the concepts employed for black and white dithers,
 *	Jim Hutchison (hutch@UCSD).
 */

#define LARGEST		(0xff)			/* 8 bits per color */

#define RG_BITS		3			/* Bits of red/green          */
#define RG_SHIFT	(8 - RG_BITS)		/* shift to get usefull bits  */
#define RG_MASK		(LARGEST >> RG_BITS)	/* masked off bits            */
#define RG_TOP		(LARGEST >> RG_SHIFT)	/* maximal value, red-green   */

#define B_BITS		2			/* Bits of blue               */
#define B_SHIFT		(8 - B_BITS)		/* shift to get usefull bits  */
#define B_MASK		(LARGEST >> B_BITS)	/* masked off bits            */
#define B_TOP		(LARGEST >> B_SHIFT)	/* maximal value, blue        */

/*
 *	2(4) by 2(4) ordered dither, it all hinges on this dither,
 *	and the color-table.  Note that dithers larger than 4x4
 *	require changes in lower code.
 */

#ifndef	LARGE_DITHER

#define DSIZE		2	/* must be a power of 2 */
#define DITH_LOG	2	/* log[2](DSIZE*DSIZE) */
#define DMASK		DSIZE-1	/* Dither mask to get position in dither */

short dither[DSIZE][DSIZE] = {
    0,	3,
    2,  1
};

#else	/* LARGE_DITHER */

#define DSIZE		4	/* must be a power of 2 */
#define DITH_LOG	4	/* log[2](DSIZE*DSIZE) */
#define DMASK		DSIZE-1	/* Dither mask to get position in dither */

short dither[DSIZE][DSIZE] = {
	0,	8,	3,	11,
	12,	4,	15,	7,
	2,	10,	1,	9,
	14,	6,	13,	5
};

#endif	/* LARGE_DITHER */

#define	MAPSIZE		256			/* size of pallet     */
#define IMAGESIZE	512			/* size of tape image */
#define IMAGE_VOL	(IMAGESIZE*IMAGESIZE)	/* volume of image    */

#define MAXPATH		1024			/* max length of filename */

struct pixrect *display;
struct pixrect *memory_frame;

unsigned char red[MAPSIZE], grn[MAPSIZE], blu[MAPSIZE];

/* default File-to-image buffers */
unsigned char rbuf[IMAGE_VOL];
unsigned char gbuf[IMAGE_VOL];
unsigned char bbuf[IMAGE_VOL];
unsigned char *pr, *pg, *pb;

/* nasty procedures */
int
min(a,b)
    int a,b;
{
    return((a > b)? b : a);
}

int
max(a,b)
    int a,b;
{
    return((a > b)? a : b);
}

main(argc,argv)
    int argc;
    char **argv;
{
    register unsigned int r_intensity, g_intensity, b_intensity;
    register unsigned int r_right, g_right, b_right;
    register unsigned int r_left, g_left, b_left;
    register unsigned int r_color, g_color, b_color;

    int imagesize, image_vol;

    unsigned int color;
    unsigned int rcolor, gcolor, bcolor;
    unsigned int dith_value;

    int fr, fg, fb;
    int i, plen;
    int x, y;
    char buf[MAXPATH];
    unsigned char *picture;


    if (argc < 2) {
	fprintf(stderr, "Usage: %s rgb-imagefile [size]\n", argv[0]);
	exit(-1);
    }

    if (argc > 2) {
	imagesize = atoi(argv[2]);
	image_vol = imagesize * imagesize;
	pr = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
	pg = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
	pb = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
    } else {
	imagesize = IMAGESIZE;
	pr = rbuf;
	pg = gbuf;
	pb = bbuf;
	image_vol = IMAGE_VOL;
    }

    strcpy(buf,argv[1]);
    plen = strlen(buf);
    buf[plen] = 'R';
    fr = open(buf, O_RDONLY, 0444);
    if (fr < 0) {
	perror(buf);
	exit(1);
    }

    buf[plen] = 'G';
    fg = open(buf, O_RDONLY, 0444);
    if (fg == 0) {
	perror(buf);
	exit(1);
    }

    buf[plen] = 'B';
    fb = open(buf, O_RDONLY, 0444);
    if (fb < 0) {
	perror(buf);
	exit(1);
    }

    display = pr_open("/dev/cgone0");
    if (display == NULL) {
	fprintf(stderr,"Color Display not available, sorry\n");
	exit (-1);
    }

    /*
     *	Generate colormap with (cycle is 8 values):
     *		32  cycles of red
     *		1   cycle  of green
     *		1/2 cycle  of blue
     *	all varying smoothely, note that an improved
     *	map which employs better graduation of color
     *	can be employed, but on our interlaced monitor
     *	this caused an extremely painful flicker.
     */
    for (i=0; i < MAPSIZE; i++) {
	red[i] = (i & 0x07) << RG_SHIFT;

	/*grn[i] = ((i & 0x38) >> 3) << RG_SHIFT;*/
	grn[i] = (i & 0x38) << 2;

	/*blu[i] = ((i & 0xc0) >> 6) << B_SHIFT;*/
	blu[i] = (i & 0xc0);
    }

    pr_putcolormap(display, 0, MAPSIZE, red, grn, blu);

    if (read(fr, pr, image_vol) <= 0)
	    perror("red");
    if (read(fg, pg, image_vol) <= 0)
	    perror("grn");
    if (read(fb, pb, image_vol) <= 0)
	    perror("blu");

    /* Get a pointer to a memory pixrect
     */
    memory_frame = mem_create(imagesize, imagesize, 8);

    /* Get a pointer to the image buffer associated with the memory pixrect
     */
    picture = mprd8_addr(mpr_d(memory_frame), 0, 0, 8);

    for (y = 0; y < imagesize; y++) {
	for (x = 0; x < imagesize; x++) {

	    r_intensity = *pr++;
	    g_intensity = *pg++;
	    b_intensity = *pb++;

	    /* 
	     * Encode base color from red-green-blue (blue-high)
	     */
	    r_right = (r_intensity >> RG_SHIFT);
	    g_right = (g_intensity >> RG_SHIFT);
	    b_right = (b_intensity >> B_SHIFT);

	    /*
	     * Divide and encode R,G,& B values to pieces of 8-bit index
	     */
	    b_color = b_right << (RG_BITS << 1);
	    g_color = g_right << RG_BITS;
	    r_color = r_right;	/* for consistancy of naming */

	    /*
	     * Here is the sticky part, dither each component.
	     *
	     * Using dither, have lesser color as background,
	     * and predominant color as paint.  choose to paint,
	     * or set to background.  Add in the colors which
	     * predominate.  Don't wrap from top to bottom.
	     * The redundant work done in the else's could
	     * have been coded out, but the result was rather
	     * ugly, and only minorly 'better'.
	     */

	    dith_value = dither[x & DMASK][y & DMASK];
	    color = 0;

	    if (r_right != RG_TOP) {
		r_left = (r_intensity + (RG_MASK - 1)) >> RG_SHIFT;
 		r_intensity = (r_intensity & RG_MASK)>>(8 - RG_BITS - DITH_LOG);
		if (r_intensity > dith_value)
		    color = r_left;
		else
		    color = r_color;
	    } else
		color = r_color;

	    if (g_right != RG_TOP) {
		g_left = (g_intensity + (RG_MASK - 1)) >> RG_SHIFT;
 		g_intensity = (g_intensity & RG_MASK)>>(8 - RG_BITS - DITH_LOG);
		if (g_intensity > dith_value)
 		    color |= (g_left << RG_BITS);
		else
		    color |= g_color;
	    } else
		color |= g_color;

	    if (b_right != B_TOP) {
		b_left = (b_intensity + (B_MASK  - 1)) >> B_SHIFT;
 		b_intensity = (b_intensity & B_MASK)>>(8 - B_BITS - DITH_LOG);
		if (b_intensity > dith_value)
 		    color |= (b_left << (RG_BITS << 1));
		else
		    color |= b_color;
	    } else
		color |= b_color;

	    *picture++ = color;
	}
    }

    /* copy the complete image to the display, center it also.
    */

    pr_rop(display,
	   max((display->pr_width - imagesize)/2, 0),
	   max((display->pr_height - imagesize)/2,0),
	   min(display->pr_width, imagesize),
	   min(display->pr_height, imagesize),
	   PIX_SRC|PIX_DONTCLIP, memory_frame, 0, 0);

    pr_close(display);
    close(fr);
    close(fg);
    close(fb);
}

-- 
/*	Jim Hutchison	UUCP:	{dcdwest,ucbvax}!sdcsvax!hutch
			ARPA:	Hutch@sdcsvax.ucsd.edu
		    [ Disclaimer eaten by a passing kiwi ]	 */