Oops, repost
Jim Hutchison
hutch at sdcsvax.UUCP
Sun Apr 20 19:20:52 AEST 1986
<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 at UCSD).
*
* The dithering is the product of madness and extrapolation
* from the concepts employed for black and white dithers,
* Jim Hutchison (hutch at 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 at sdcsvax.ucsd.edu
[ Disclaimer eaten by a passing kiwi ] */
More information about the Comp.sources.unix
mailing list