home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- Copyright (c) 1988 by Hong Min
-
- compile : cc -O -o 8to1 8to1.c -lpixrect
-
- The program 8to1 converts a 8-bit depth sun raster file (both color,
- i.e. rgb are different, and grey, i.e. rgb are the same, and both
- standard format and byte-encoded format) to a 1-bit depth mono sun
- raster file. If your color image has no colormap, this program would
- provide a default grey scale color map. It implements several halftone
- algorithms from Digital Halftones by Dot Diffusion in acm Transactions
- on Graphics, such as error diffusion, ordered dither and dot diffusion
- with and without edge enhancement. Just type 8to1, it will give you
- the usage.
-
- This program was written by :
-
- Hong Min
- Computer Science Department
- SUNY at Stony Brook
- e-mail address :
- UUCP: {allegra, philabs, pyramid, research}!sbcs!rainbow
- ARPA-Internet: rainbow@sbcs.sunysb.edu
- CSnet: rainbow@suny-sb
-
- Everyone is welcome to write to me if you like the program or not.
- And welcome to optimize the code, as I haven't fooled with it to
- make it efficient yet.
-
- Enjoy!
-
- ****************************************************************************/
-
-
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <pixrect/pixrect.h>
- #include <pixrect/memvar.h>
- #include <pixrect/pr_util.h>
- #include <pixrect/pr_io.h>
- #include <rasterfile.h>
-
- #define ORDER 16 /* dither matrix order */
- #define WHITE 0 /* background color */
- #define BLACK ~0 /* foreground color */
- #define FALSE 0
- #define TRUE 1
- #define ALPHA 7
- #define BETA 3
- #define GAMMA 5
- #define DELTA 1
-
- short **A, **B;
- int ordered_dither[8][8] = { 0, 32, 8, 40, 2, 34, 10, 42,
- 48, 16, 56, 24, 50, 18, 58, 26,
- 12, 44, 4, 36, 14, 46, 6, 38,
- 60, 28, 52, 20, 62, 30, 54, 22,
- 3, 35, 11, 43, 1, 33, 9, 41,
- 51, 19, 59, 27, 49, 17, 57, 25,
- 15, 47, 7, 39, 13, 45, 5, 37,
- 63, 31, 55, 23, 61, 29, 53, 21 };
- int dot_diffusion[8][8] = { 34, 48, 40, 32, 29, 15, 23, 31,
- 42, 58, 56, 53, 21, 5, 7, 10,
- 50, 62, 61, 45, 13, 1, 2, 18,
- 38, 46, 54, 37, 25, 17, 9, 26,
- 28, 14, 22, 30, 35, 49, 41, 33,
- 20, 4, 6, 11, 43, 59, 57, 52,
- 12, 0, 3, 19, 51, 63, 60, 44,
- 24, 16, 8, 27, 39, 47, 55, 36 };
- int reverse_matrix[64] = { 49, 21, 22, 50, 41, 13, 42, 14,
- 58, 30, 15, 43, 48, 20, 33, 5,
- 57, 29, 23, 51, 40, 12, 34, 6,
- 56, 28, 31, 59, 32, 4, 35, 7,
- 3, 39, 0, 36, 63, 27, 24, 60,
- 2, 38, 8, 44, 55, 19, 25, 61,
- 1, 37, 16, 52, 47, 11, 26, 62,
- 10, 46, 9, 45, 54, 18, 17, 53 };
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- register colormap_t colormap;
- register unsigned char *map;
- register struct rasterfile rh;
- register Pixrect *pr = 0;
- register int i, default_map = FALSE;
- int option;
-
- if ((argc > 4) || (argc < 2)) {
- fprintf(stderr, "Usage: %s option [infile [outfile]]\n", argv[0]);
- fprintf(stderr, "option : 0 -- error diffusion for grey scale\n");
- fprintf(stderr, " 1 -- ordered dither for grey scale\n");
- fprintf(stderr, " 2 -- dot diffusion for grey scale\n");
- fprintf(stderr, " 3 -- error diffusion for grey scale with edge enhancement\n");
- fprintf(stderr, " 4 -- ordered dither for grey scale with edge enhancement\n");
- fprintf(stderr, " 5 -- dot diffusion for grey scale with edge enhancement\n");
- fprintf(stderr, " 6 -- error diffusion for color\n");
- fprintf(stderr, " 7 -- ordered dither for color\n");
- fprintf(stderr, " 8 -- dot diffusion for color\n");
- fprintf(stderr, " 9 -- error diffusion for color with edge enhancement\n");
- fprintf(stderr, " 10 -- ordered dither for color with edge enhancement\n");
- fprintf(stderr, " 11 -- dot diffusion for color with edge enhancement\n");
- exit(1);
- }
-
- sscanf(argv[1], "%d", &option);
-
- /* open the input file if specified */
- if ((argc > 2) && (freopen(argv[2], "r", stdin) == NULL)) {
- fprintf(stderr, "can't open infile %s for read!\n", argv[2]);
- exit(1);
- }
-
- /* open the output file if specified */
- if ((argc > 3) && (freopen(argv[3], "w", stdout) == NULL)) {
- fprintf(stderr, "can't open outfile %s for write!\n", argv[3]);
- exit(1);
- }
-
- /* Load the input rasterfile header */
- if (pr_load_header(stdin, &rh)) {
- fprintf(stderr, "read rasterfile header error\n");
- exit(1);
- }
-
- if (rh.ras_depth != 8) {
- fprintf(stderr, "input file is not a 8 bits deep\n");
- exit(1);
- }
-
- /* Load the colormap */
- colormap.type = RMT_NONE;
- if (pr_load_colormap(stdin, &rh, &colormap)) {
- fprintf(stderr, "read rasterfile header error\n");
- exit(1);
- }
-
- if (colormap.type != RMT_NONE &&
- (colormap.type != RMT_EQUAL_RGB || colormap.length < 256)) {
- fprintf(stderr,"input has unsupported colormap type or length\n");
- exit(1);
- }
-
- if ((colormap.type == RMT_NONE) && (colormap.length == 0)) {
- default_map = TRUE;
- map = (unsigned char *) malloc(256);
- for (i=0; i<256; i++)
- map[i] = i;
- }
-
- if (rh.ras_type != RT_OLD && rh.ras_type != RT_STANDARD &&
- !(pr = pr_load_image(stdin, &rh, &colormap))) {
- fprintf(stderr, "error reading rasterfile\n");
- exit(1);
- }
-
- /* Write new header */
- rh.ras_type = RT_STANDARD;
- rh.ras_depth = 1;
- rh.ras_length = mpr_linebytes(rh.ras_width, 1) * rh.ras_height;
- rh.ras_maptype = RMT_NONE;
- rh.ras_maplength = 0;
-
- if (pr_dump_header(stdout, &rh, (colormap_t *) 0) == PIX_ERR) {
- fprintf(stderr, "error saving raster file header!\n");
- exit(1);
- }
-
- if (rh.ras_width <= 0 || rh.ras_height <= 0)
- exit(1);
- else {
- A = (short **) malloc((rh.ras_width+3)*sizeof(short *));
- B = (short **) malloc((rh.ras_width+3)*sizeof(short *));
- for(i=0; i<rh.ras_width+3; i++) {
- A[i] = (short *)malloc((rh.ras_height+3)*sizeof(short));
- B[i] = (short *)malloc((rh.ras_height+3)*sizeof(short));
- }
- }
-
- if (!default_map)
- map = colormap.map[0];
-
- if (pr)
- switch (option) {
- case 6 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 0 : error_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 0, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 7 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 1 : ordered_dither_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 0, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 8 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 2 : dot_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 0, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 9 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 3 : error_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 1, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 10 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 4 : ordered_dither_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 1, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 11 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 5 : dot_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 1, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- }
- else
- switch (option) {
- case 6 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 0 : error_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 0,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 7 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 1 : ordered_dither_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 0,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 8 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 2 : dot_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 0,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 9 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 3 : error_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 1,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 10 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 4 : ordered_dither_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 1,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 11 : map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 5 : dot_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 1,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- }
- }
-
- color_map_3_to_1(colormap, map)
- register colormap_t colormap;
- register unsigned char *map;
- {
- register unsigned long tmp, i;
-
- for (i=0; i<256; i++) {
- tmp = colormap.map[0][i]*77 + colormap.map[1][i]*151 + colormap.map[2][i]*28;
- map[i] = tmp >> 8;
- }
- }
-
-
- edge_enhancement(width, height, off)
- register int width, height, off;
- {
- register int i, j, x, y;
-
- B[off][off] = A[off][off]*6 - A[off][off+1] - A[off+1][off] - A[off+1][off+1];
- B[off][off+height-1] = A[off][off+height-1]*6 - A[off][off+height-2] - A[off+1][off+height-1] - A[off+1][off+height-2];
- B[off+width-1][off] = A[off+width-1][off]*6 - A[off+width-1][off+1] - A[off+width-2][off] - A[off+width-2][off+1];
- B[off+width-1][off+height-1] = A[off+width-1][off+height-1]*6 - A[off+width-1][off+height-2] - A[off+width-2][off+height-1] - A[off+width-2][off+height-2];
-
- for (i=1; i<width-1; i++)
- B[off+i][off+0] = A[off+i][off+0]*6 - A[off+i-1][off+0] - A[off+i+1][off+0] - A[off+i-1][off+1] - A[off+i][off+1] - A[off+i+1][off+1];
- for (i=1; i<width-1; i++)
- B[off+i][off+height-1] = A[off+i][off+height-1]*6 - A[off+i-1][off+height-1] - A[off+i+1][off+height-2] - A[off+i-1][off+height-2] - A[off+i][off+1] - A[off+i+1][off+height-2];
- for (i=1; i<height-1; i++)
- B[off+0][off+i] = A[off+0][off+i]*6 - A[off+0][off+i-1] - A[off+0][off+i+1] - A[off+1][off+i-1] - A[off+1][off+i] - A[off+1][off+i+1];
- for (i=1; i<height-1; i++)
- B[off+width-1][off+i] = A[off+width-1][off+i]*6 - A[off+width-1][off+i-1] - A[off+width-1][off+i+1] - A[off+width-2][off+i-1] - A[off+width-2][off+i] - A[off+width-2][off+i+1];
-
- for(i=1; i<width-1; i++)
- for(j=1; j<height-1; j++) {
- B[off+i][off+j] = A[off+i][off+j]*10;
- for(x=i-1; x<=i+1; x++)
- for(y=j-1; y<=j+1; y++)
- B[off+i][off+j] -= A[off+x][off+y];
- }
-
- for(i=0; i<width; i++)
- for(j=0; j<height; j++)
- A[off+i][off+j] = B[off+i][off+j];
- }
-
-
- int index(x, y, w, pad)
- register int x, y, w, pad;
- {
- return(x+y*(w+pad));
- }
-
- error_diffusion(width, height, out, edge)
- register int width, height;
- register FILE *out;
- register int edge;
- {
- register int err, mono_pad;
- register u_short dtmp;
- register u_long i, j;
-
- mono_pad = mpr_linebytes(width, 1)*8 - width;
-
- if (edge)
- edge_enhancement(width, height, 1);
-
- for(j=1; j<height+1; j++) {
- for(i=1; i<width+1; i++) {
- dtmp <<= 1;
- if (A[i][j] > 128)
- err = A[i][j] - 256;
- else {
- err = A[i][j];
- dtmp |= 1;
- }
- A[i+1][j] += (err*ALPHA) >> 4;
- A[i-1][j+1] += (err*BETA) >> 4;
- A[i][j+1] += (err*GAMMA) >> 4;
- A[i+1][j+1] += (err*DELTA) >> 4;
- if (((i-1) % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- for(i=width+1; i<=width+mono_pad; i++) {
- dtmp <<= 1;
- if (((i-1) % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- }
- }
-
- /* Compute pixel values using error diffusion */
- error_diffusion_image(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register u_char *in;
- register FILE *out;
- register int edge_enhance, pad;
- {
- register int i, j;
-
- for(j=1; j<height+1; j++)
- for(i=1; i<width+1; i++)
- A[i][j] = map[*(in+index(i-1, j-1, width, pad))];
-
- error_diffusion(width, height, out, edge_enhance);
- }
-
-
- /* Compute pixel values using error diffusion */
- error_diffusion_file(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register FILE *in, *out;
- register int edge_enhance, pad;
- {
- register int i, j, c;
-
- for(j=1; j<height+1; j++) {
- for(i=1; i<width+1; i++) {
- if ((c = getc(in)) == EOF) {
- fprintf(stderr, "error reading raster data!\n");
- exit(1);
- }
- A[i][j] = map[c];
- }
- for(i=width; i<width+pad; i++)
- if ((c = getc(in)) == EOF)
- fprintf(stderr, "error reading raster data!\n");
- }
-
- error_diffusion(width, height, out, edge_enhance);
- }
-
- ordered(width, height, out, edge)
- register int width, height;
- register FILE *out;
- register int edge;
- {
- register int mono_pad;
- register u_short dtmp;
- register u_long i, j;
-
- mono_pad = mpr_linebytes(width, 1)*8 - width;
-
- if (edge)
- edge_enhancement(width, height, 0);
-
- for(j=0; j<8; j++)
- for(i=0; i<8; i++)
- ordered_dither[i][j] = ordered_dither[i][j]*4 + 2;
-
- for(j=0; j<height; j++) {
- for(i=0; i<width; i++) {
- dtmp <<= 1;
- if (A[i][j] >= ordered_dither[i%8][j%8])
- dtmp |= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- for(i=width; i<width+mono_pad; i++) {
- dtmp <<= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- }
- }
-
- ordered_dither_image(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register u_char *in;
- register FILE *out;
- register int edge_enhance, pad;
- {
- register int i, j;
-
- for(j=0; j<height; j++)
- for(i=0; i<width; i++)
- A[i][j] = 256 - map[*(in+index(i, j, width, pad))];
-
- ordered(width, height, out, edge_enhance);
- }
-
-
- ordered_dither_file(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register FILE *in, *out;
- register int edge_enhance, pad;
- {
- register int i, j, c;
-
- for(j=0; j<height; j++) {
- for(i=0; i<width; i++) {
- if ((c = getc(in)) == EOF) {
- fprintf(stderr, "error reading raster data!\n");
- exit(1);
- }
- A[i][j] = 256 - map[c];
- }
- for(i=width; i<width+pad; i++)
- if ((c = getc(in)) == EOF)
- fprintf(stderr, "error reading raster data!\n");
- }
-
- ordered(width, height, out, edge_enhance);
- }
-
- int weight(x, y)
- register int x,y;
- {
- return(3 - x*x - y*y);
- }
-
- dot(width, height, out, edge)
- register int width, height;
- register FILE *out;
- register int edge;
- {
- register int k, u, v, err, w, mono_pad;
- register u_short dtmp;
- register u_long i, j;
-
- mono_pad = mpr_linebytes(width, 1)*8 - width;
-
- if (edge)
- edge_enhancement(width, height, 0);
-
- for(k=0; k<64; k++) {
- for(i=reverse_matrix[k]/8; i<width; i+=8)
- for(j=reverse_matrix[k]%8; j<height; j+=8) {
- if (A[i][j] > 128)
- B[i][j] = 0;
- else
- B[i][j] = 1;
- err = A[i][j] - (1 - B[i][j])*256;
- w = 0;
- for(u=i-1; u<=i+1; u++)
- for(v=j-1; v<=j+1; v++)
- if ((u>=0) && (v>=0) && (dot_diffusion[u%8][v%8] > k))
- w += weight(u-i, v-j);
- if (w > 0) {
- for(u=i-1; u<=i+1; u++)
- for(v=j-1; v<=j+1; v++)
- if ((u>=0)&&(v>=0)&&(dot_diffusion[u%8][v%8]>k))
- A[u][v] += err * weight(u-i, v-j) / w;
- }
- }
- }
-
- for(j=0; j<height; j++) {
- for(i=0; i<width; i++) {
- dtmp <<= 1;
- if (B[i][j])
- dtmp |= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- for(i=width; i<width+mono_pad; i++) {
- dtmp <<= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- }
- }
-
-
- dot_diffusion_image(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register u_char *in;
- register FILE *out;
- register int edge_enhance, pad;
- {
- register int i, j;
-
- for(j=0; j<height; j++)
- for(i=0; i<width; i++)
- A[i][j] = map[*(in+index(i, j, width, pad))];
-
- dot(width, height, out, edge_enhance);
- }
-
- dot_diffusion_file(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register FILE *in, *out;
- register int edge_enhance, pad;
- {
- register int i, j, c;
-
- for(j=0; j<height; j++) {
- for(i=0; i<width; i++) {
- if ((c = getc(in)) == EOF) {
- fprintf(stderr, "error reading raster data!\n");
- exit(1);
- }
- A[i][j] = map[c];
- }
- for(i=width; i<width+pad; i++)
- if ((c = getc(in)) == EOF)
- fprintf(stderr, "error reading raster data!\n");
- }
-
- dot(width, height, out, edge_enhance);
- }
-
-