segel@quanta.eng.ohio-state.edu (VAXEN Assasin) (02/10/89)
I have been working on a small project which involves capturing an image via a camera and then converting its image to a raster format. I was wondering if anyone knew of a better dithering program than rasfilter8to1. The time required to calculate the conversion should not be a factor. I am looking to achieve the highest quality of output. Part of this project is to develop rasters for the backrounds on the suns and as well as to create brush images. Can anyone also recommend any free toolkits? (I don't have a budget) -mike S. PS I would like to thank cyrus.pprg.unm.edu for answering my questions among other things! -- -Mike Segel segel@icarus.eng.ohio-state.edu (614) 294-3350 "These opinions are my own and in no way reflect those of the University or the E E Dept.(Although there are those who probably share them!)
jonathan@jvc.UUCP (Jonathan Hue) (02/17/89)
In article <1747@quanta.eng.ohio-state.edu>, segel@quanta.eng.ohio-state.edu (VAXEN Assasin) writes: > > I have been working on a small project which involves > capturing an image via a camera and then converting its image > to a raster format. I was wondering if anyone knew > of a better dithering program than rasfilter8to1. I took the "grey.c" program posted here a while ago and wedged in my Floyd-Steinberg (error diffusion) dither routine, to come up with a new program I call "bw". You'll need the pr_stream.c and ntsc.h from that posting to compile. In case it's not obvious, type cc -O -o bw bw.c pr_stream.c -lpixrect. I've never tried this with an image which wasn't a multiple of 8 in width, so I don't know if it works - it's supposed to. If you want really good images, you'll probably want to apply some unsharp masking while it's in 8-bit greyscale before you apply "bw" to it. Also, it's probably not a linear function between % of white pixels and intensity, so you may want to pass the data through a look-up table before calling FsDither(). Jonathan Hue uunet!jvc!jonathan ----------------------------Cut Here------------------------------ echo x - bw.c sed 's/^X//' >bw.c <<'*-*-END-of-bw.c-*-*' X#include <sys/types.h> X#include <stdio.h> X#include <pixrect/pixrect_hs.h> X#include <memory.h> X#include "ntsc.h" X X Xstatic char *usage = "usage: \"bw [ infile [ outfile]]\"\n"; X Xextern int errno; Xextern char *sys_errlist[]; Xextern char *malloc(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char *infile, *outfile; X struct rasterfile header, outheader; X colormap_t colormap; X int linebytes, outlinebytes; X unsigned char *inline, *outline; X register int i, j; X register unsigned char *inptr; X short *TempLine, *TempErrors; X register short *TempPtr; X int TempPixels; X X infile = outfile = NULL; X X while (--argc) X { X ++argv; X if (!infile) X infile = *argv; X else if (!outfile) X outfile = *argv; X else X { X fprintf(stderr, usage); X exit(1); X } X } X X if (infile != NULL) X if (freopen(infile, "r", stdin) == NULL) X { X fprintf(stderr, "bw: can't open input file %s, %s\n%s", X infile, sys_errlist[errno], usage); X exit(1); X } X if (outfile != NULL) X if (freopen(outfile, "w", stdout) == NULL) X { X fprintf(stderr, "bw: can't open output file %s, %s\n%s", X outfile, sys_errlist[errno], usage); X exit(1); X } X if (pr_load_header(stdin, &header) != 0 || X pr_load_colormap(stdin, &header, &colormap) != 0) X { X fprintf(stderr, "error reading rasterfile header\n"); X exit(1); X } X switch (header.ras_depth) X { X case 8: X linebytes = header.ras_width; X break; X case 24: X linebytes = header.ras_width * 3; X break; X case 32: X linebytes = header.ras_width * 4; X break; X default: X fprintf(stderr, "bw: only works with 32, 24 or 8 bit images\n"); X exit(1); X } X linebytes += linebytes % 2; X X TempPixels = header.ras_width; X outlinebytes = (header.ras_width + 7) >> 3; X if (outlinebytes & 0x1) X outlinebytes++; /* always pad to 16 bits */ X X X outheader = header; X outheader.ras_depth = 1; X outheader.ras_type = RT_STANDARD; X outheader.ras_maptype = RMT_NONE; X outheader.ras_length = outlinebytes * outheader.ras_height; X X X pr_dump_header(stdout, &outheader, (colormap_t *) NULL); X X pr_read_init(&header); X X inline = (unsigned char *) malloc((u_int) linebytes); X outline = (unsigned char *) malloc((u_int) outlinebytes); X X /* the +2 is for one pixel borders on each side */ X TempLine = (short *) malloc((u_int) ((TempPixels + 2) * sizeof(short))); X TempErrors = (short *) malloc((u_int) ((TempPixels + 2) * sizeof(short))); X memset((char *) TempErrors, 0, ((TempPixels + 2) * sizeof(short))); X X for (i = 0; i < outheader.ras_height; ++i) X { X pr_get_bytes(stdin, &header, linebytes, inline); X inptr = inline; X TempPtr = TempLine + 1; X X for (j = 0; j < TempPixels; ++j) X { X register int r, g, b; X switch (header.ras_depth) X { X case 8: X r = g = b = *inptr++; X break; X case 32: X ++inptr; X case 24: X b = *inptr++; X g = *inptr++; X r = *inptr++; X break; X } X if (header.ras_maptype == RMT_EQUAL_RGB) X { X r = colormap.map[0][r]; X g = colormap.map[1][g]; X b = colormap.map[2][b]; X } X /* NTSC weights (.3,.59,.11) */ X *TempPtr++ = ((ntscr[r] + ntscg[g] + ntscb[b]) / 256) + X TempErrors[j + 1]; X } X memset((char *) TempErrors, 0, ((TempPixels + 2) * sizeof(short))); X memset((char *) outline, 0, outlinebytes); X FsDither(TempLine, TempErrors, outline, i, TempPixels); X fwrite((char *) outline, 1, outlinebytes, stdout); X } X fclose(stdout); X} X X X X/* X * Apply Floyd-Steinberg dither to 8-bit data X */ XFsDither(EightBitPtr, ErrorTerms, OneBitPtr, row, nbytes) Xregister short *EightBitPtr; /* Line of input data with 1 pixel borders */ Xregister short *ErrorTerms; /* Line of error terms with 1 pixel borders */ Xregister u_char *OneBitPtr; /* Line of output data */ Xint row, nbytes; /* row (for going -> or <-) */ X{ X register int i, error; X register u_char pattern; X X if (row & 1) /* go right to left */ X { X if ((nbytes & 7) == 0) X pattern = 0x01; X else X pattern = 1 << (8 - (nbytes & 7)); X EightBitPtr += nbytes; X OneBitPtr += ((nbytes + 7) >> 3) - 1; X for (i = nbytes; i > 0; i--) X { X if (*EightBitPtr < 127) X { X error = *EightBitPtr; X *OneBitPtr |= pattern; X } X else X error = *EightBitPtr - 255; X *(EightBitPtr - 1) += (error * 7) / 16; X ErrorTerms[i + 1] += (error * 3) / 16; X ErrorTerms[i] += (error * 5) / 16; X ErrorTerms[i - 1] += error / 16; X if (pattern == 0x80) X { X pattern = 0x1; X OneBitPtr--; X } X else X pattern <<= 1; X EightBitPtr--; X } X } X else /* go left to right */ X { X EightBitPtr++; X pattern = 0x80; X for (i = 1; i <= nbytes; i++) X { X if (*EightBitPtr < 127) X { X error = *EightBitPtr; X *OneBitPtr |= pattern; X } X else X error = *EightBitPtr - 255; X *(EightBitPtr + 1) += (error * 7) / 16; X ErrorTerms[i - 1] += (error * 3) / 16; X ErrorTerms[i] += (error * 5) / 16; X ErrorTerms[i + 1] += error / 16; X if (pattern == 0x01) X { X pattern = 0x80; X OneBitPtr++; X } X else X pattern >>= 1; X EightBitPtr++; X } X } X} X *-*-END-of-bw.c-*-* exit
jonathan@jvc.UUCP (Jonathan Hue) (02/17/89)
I screwed up. A lot of raster file loaders pay attention to ras_maplength even when ras_maptype is RMT_NONE. It should always be 0 for these 1-bit images, so here's a patch. The program as distributed uses the maplength of the original. The bug only shows up when your original has a colormap. Sorry for the inconvenience. *** bw.dist Thu Feb 16 16:19:40 1989 --- bw.c Thu Feb 16 16:24:52 1989 *************** *** 90,96 **** outheader.ras_type = RT_STANDARD; outheader.ras_maptype = RMT_NONE; outheader.ras_length = outlinebytes * outheader.ras_height; ! pr_dump_header(stdout, &outheader, (colormap_t *) NULL); --- 90,96 ---- outheader.ras_type = RT_STANDARD; outheader.ras_maptype = RMT_NONE; outheader.ras_length = outlinebytes * outheader.ras_height; ! outheader.ras_maplength = 0; /* no color map */ pr_dump_header(stdout, &outheader, (colormap_t *) NULL); -Jonathan uunet!jvc!jonathan