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 ] */