/* dwip.c: Daisy Wheel IFF Printer utility. * Placed in the public domain by the author: * Ken Van Camp * Digitized Data Display Systems * P.O. Box 878 * Marshalls Creek, PA 18335-0878 * Version 1.0 March 12, 1988 * Based heavily on the public domain jiff and plop programs by Jim Kent */ #include #include #include #include #include #include #include #include #include "jiff.h" #define PARANOID /* variables specific to dwip: */ typedef float REAL; struct dev_info { REAL hpitch, vpitch, /* horizontal & vertical dot pitch (dpi) */ hlength, vlength; /* horiz & vert length of tot pic (inches) */ int xstart, ystart, /* starting position (in dots) */ xstop, ystop, /* stopping position (in dots) */ width, height; /* area to print (in dots) */ }; struct dev_info scr = { /* screen device info */ XMAX/10.25, /* hpitch */ YMAX/7.15, /* vpitch */ 0., 0., /* hlength, vlength (computed, not initialized) */ 0, 0, /* xstart, ystart */ 0, 0, /* xstop, ystop (computed, not initialized) */ XMAX, YMAX /* width, height */ }; struct dev_info ptr = { /* printer device info */ 10., /* hpitch */ 6., /* vpitch */ 0., 0., /* hlength, vlength (computed, not initialized) */ 0, 0, /* xstart, ystart (unused on printer) */ 0, 0, /* xstop, ystop (unused on printer) */ 135, /* width (135 columns of text) */ 0 /* height (computed, not initialized) */ }; REAL hreduce, /* reduction factor (dots per dot) screen to ptr */ vreduce, /* same, but vertical */ r_intens = 1.0, /* red color intensity */ g_intens = 0.7, /* green color intensity */ b_intens = 1.0; /* blue color intensity */ int fileopen=0, /* is an output file open? */ sideopt=0, /* print it sideways? */ dotopt=0, /* use dots instead of characters? */ viewopt=0, /* view only (don't print)? */ modopt=0, /* modify (invert) the image? */ autopt=1, /* automatically start up background printing? */ nplanes, /* # bitplanes used in this picture */ ncolors, /* # colors in the pallette */ universal=0, /* "universal" printing option (use backspaces) */ testpat=0, /* just print a test pattern? */ scrn_alloc=0; /* has a screen been allocated? */ /* these are the RGB components of all the colors in the palette: */ unsigned short rcol[MAXCOL], gcol[MAXCOL], bcol[MAXCOL]; FILE *outfile, *fopen(); /* output file descriptor */ char *bplane[PLANES], /* ptrs to each bitplane */ *filename, /* output file name */ init_string[160] = "", /* initialization string to printer */ eol_string[20] = "\n"; /* end-of-line string */ /* following is for the line buffers. Each buffer holds one line of * data to be output to the printer, separated by a carriage return */ #define NBUFS 6 /* max #chars can be overstruck for 1 dot */ char buf[NBUFS][XMAX]; /* buffers for line output */ int buf_used[NBUFS]; /* flag: was buffer used in this line? */ char *documentation[] = { "dwip: public domain Daisy Wheel IFF Printer utility v1.0 by Ken Van Camp", " usage: dwip [options] files --where valid options are:", " -lval set leftmost location on screen (default 0)", " -tval set top location on screen (default 0)", " -wval set width of screen area to print (default 320)", " -hval set height of screen area to print (default 200)", " -pval set printer pitch (default 10)", " -cval set # columns to use across printer (default 135)", " -nval set # lines per inch on printer (default 6)", " -istring set initialization string (default is none)", " -estring set end-of-line string (default is newline)", " -ofile send output to named file (default is RAM:dwXXXX)", " -s toggle to print sideways (default OFF)", " -m toggle to modify (negative) picture (default OFF)", " -rval set red relative intensity (default 1.0)", " -gval set green relative intensity (default 0.7)", " -bval set blue relative intensity (default 1.0)", " -vtime view file for time seconds, instead of printing", 0 }; /* Following are strings to send for each of the 37 character grey scales. * This table came from: * "Considerations for Efficient Picture Output via Lineprinter" * by Peter Henderson and Steven Tanimoto, Computer Graphics & Image * Processing, Vol 3. 1974, pp. 327-335. */ #define MAXSHADES 37 char *letters[MAXSHADES] = { /* 0 next */ "MW#O0+", "MW#O0 ", "MW#O+ ", "MW#0 ", "MW#O ", "MW# ", "MW0 ", "MWO ", "H#+ ", "H#- ", /* 10 next */ "H# ", "H* ", "H+ ", "X+ ", "H- ", "X- ", "O- ", "Z- ", "W ", "M ", /* 20 next */ "N ", "H ", "0 ", "O ", "S ", "== ", "I ", "* ", "+- ", "+ ", /* 30 next */ "= ", ": ", "-- ", ". ", "- ", "` ", " " }; struct ILBM_info *s_info; /*This should be in exec/libraries.h */ extern struct Library *OpenLibrary(); /*This should be in intuition/intuition.h */ extern struct Screen *OpenScreen(); struct Library *GfxBase = NULL; struct Library *LayersBase = NULL; struct Library *IntuitionBase = NULL; struct Screen *DwipScreen = NULL; struct TextAttr DwipFont = { "topaz.font", /* I think this is the ROM font */ 8, 0, 0, }; /* a NewScreen - I don't know what half of this means either */ static struct NewScreen DwipNewScreen = { 0, 0, XMAX, YMAX, PLANES, 0, 1, 0, CUSTOMSCREEN, &DwipFont, "dwip dwip dwip", NULL, NULL, }; /* To use clip blit need a RastPort. */ struct RastPort DwipRastPort; /* help: Give good help */ void help (hp) char **hp; { void dwip_cleanup(); register char **dp; for (dp = hp; *dp; dp++) printf ("%s\n", *dp); dwip_cleanup(); exit(1); } /* help */ /*put_ea_cmap given an ea-type color map: an array of unsigned chars of form ea_cmap[] = {r, g, b, r, g, b...} turn it into an amiga-type color map: an array of unsigned short of form amiga_cmap = {0xrgb, 0xrgb, ...} and then tell Dale these are the colors we want for our viewport */ void put_ea_cmap(cmap, colors) unsigned char *cmap; int colors; { unsigned short amy_cmap[MAXCOL]; int i; unsigned char r, g, b; if (colors > MAXCOL) /*color clipping*/ colors = MAXCOL; ncolors = colors; for (i=0; i> 4; gcol[i] = (cmap[1] & 0xf0) >> 4; bcol[i] = (cmap[2] & 0xf0) >> 4; amy_cmap[i] = ((cmap[0] & 0xf0) << 4) + (cmap[1] & 0xf0) + ((cmap[2] & 0xf0) >> 4); cmap += 3; } LoadRGB4( &DwipScreen->ViewPort, amy_cmap, (long)colors); } /* put_ea_cmap */ /* back out backwards */ void dwip_cleanup() { if (DwipScreen != NULL) CloseScreen(DwipScreen); if (IntuitionBase != NULL) CloseLibrary(IntuitionBase); if (LayersBase != NULL) CloseLibrary(LayersBase); if (GfxBase != NULL) CloseLibrary(GfxBase); if (fileopen){ fileopen = 0; fclose (outfile); } if (scrn_alloc){ scrn_alloc = 0; free_planes (&s_info->bitmap); } } /* dwip_cleanup */ /* getbit: return value (0 or 1) of specified bit of supplied byte. * Why didn't I put this in a macro? */ int getbit (b, n) char b; int n; { return (b>>n & 1); } /* getbit */ /* get_shade: return the shade of the specified pixel */ int get_shade (x, y) int x, y; /* coords of the pixel */ { int color_num, /* color number of the pixel */ j, /* index to bitplanes */ shade, /* shade of the pixel */ byte_num, /* byte # offset within bitplane */ bit; /* bit # within byte */ char *b; /* actual byte address */ byte_num = y * 40 + x / 8; bit = 7 - (x % 8); /* bits are in reverse order! */ /* find color # */ color_num = 0; for (j = 0; j < nplanes; j++){ b = bplane[j] + (char *)byte_num; color_num += getbit (*b, bit) << j; } if (color_num > ncolors){ #ifdef PARANOID printf ("Unknown color #%d\n", color_num); #endif PARANOID return(0); }else{ shade = (int) ((REAL)rcol[color_num] * r_intens + (REAL)gcol[color_num] * g_intens + (REAL)bcol[color_num] * b_intens); if (modopt) /* inverse picture */ return (MAXSHADES - shade); else /* normal picture */ return (shade); } /* if color_num */ } /* get_shade */ /* charshade: Returns the string of characters to send to produce a given * shade of grey. */ char *charshade (shade) int shade; { if (shade < MAXSHADES) return (letters[shade]); else /* This makes more pixels white than really should be. */ return (letters[MAXSHADES-1]); } /* set_values: Set the screen printing parameters. This routine is called * before every picture is printed, in case anything has changed since * the last picture. */ void set_values () { if (scr.xstart < 0) scr.xstart = 0; if (scr.ystart < 0) scr.ystart = 0; if (scr.width + scr.xstart > XMAX) scr.width = XMAX - scr.xstart; if (scr.height + scr.ystart > YMAX) scr.height = YMAX - scr.ystart; ptr.hlength = ptr.width / ptr.hpitch; scr.hlength = scr.width / scr.hpitch; scr.vlength = scr.height / scr.vpitch; if (! sideopt){ /* normal print */ hreduce = (REAL) scr.width / ptr.width; ptr.vlength = scr.vlength * ptr.hlength / scr.hlength; }else{ /* sideways print */ hreduce = (REAL) scr.height / ptr.width; ptr.vlength = scr.hlength * ptr.hlength / scr.hlength; } ptr.height = ptr.vlength * ptr.vpitch; vreduce = (REAL) scr.height / ptr.height; scr.xstop = scr.xstart + scr.width - 1; scr.ystop = scr.ystart + scr.height - 1; #ifdef DEBUG printf("Screen : pitches=%lf,%lf lengths=%lf,%lf width=%d height=%d\n", scr.hpitch, scr.vpitch, scr.hlength, scr.vlength, scr.width, scr.height); printf("Printer: pitches=%lf,%lf lengths=%lf,%lf width=%d height=%d\n", ptr.hpitch, ptr.vpitch, ptr.hlength, ptr.vlength, ptr.width, ptr.height); printf("reduce=%lf,%lf start=%d,%d stop=%d,%d\n", hreduce, vreduce, scr.xstart, scr.ystart, scr.xstop, scr.ystop); #endif } /* set_values */ /* eval_strg: evaluate 3-digit decimal constants within a string */ void eval_strg (s) char *s; { int i, j; char t[80], tmp[4]; tmp[3] = NULL; i = j = 0; while (s[i] != NULL){ if (s[i] == '\\'){ /* decode a decimal constant */ tmp[0] = s[++i]; tmp[1] = s[++i]; tmp[2] = s[++i]; t[j++] = (char) atoi (tmp); }else t[j++] = s[i]; i++; } t[j] = NULL; strcpy (s, t); } /* eval_strg */ /* eval_arg: Evaluate a command-line argument, and set appropriate global * variables. Returns 1 if just an input filename, 0 if a valid option. * Doesn't return at all if an invalid option. */ int eval_arg (arg) char *arg; { void help(), eval_strg(); double atof(); int i, /* char array index */ optused; /* flag: was complete option used? */ char c; /* next char to process */ if (arg[0] == '-'){ /* cmmd line option: interpret */ i = 1; optused = 0; /* could be more than one option per minus sign */ c = arg[i]; /* do until delimiter between arguments is found: either a space * or null */ while (c && c != ' ' && !optused){ i++; switch (c){ case '?': help (documentation); break; case 'a': /* auto-printing option */ autopt = !autopt; break; case 'b': /* set blue value */ b_intens = atof (&arg[i]); optused++; break; case 'c': /* set # columns on printer */ ptr.width = atoi (&arg[i]); optused++; break; case 'd': /* dot (dithering) option */ dotopt = !dotopt; printf ("Dot option not implemented yet\n"); break; case 'e': /* end-of-line string */ /* sprintf (eol_string, &arg[i]); */ strcpy (eol_string, &arg[i]); eval_strg (eol_string); optused++; break; case 'g': /* set green value */ g_intens = atof (&arg[i]); optused++; break; case 'h': /* set screen height */ scr.height = atoi (&arg[i]); optused++; break; case 'i': /* initialization string */ /* sprintf (init_string, &arg[i]); */ strcpy (init_string, &arg[i]); eval_strg (init_string); optused++; break; case 'l': /* set left edge of screen to print */ scr.xstart = atoi (&arg[i]); optused++; break; case 'm': /* set "modified" flag (inverse image) */ modopt = !modopt; break; case 'n': /* set # lines per inch on printer */ ptr.vpitch = atoi (&arg[i]); optused++; break; case 'o': /* output filename */ /* strcpy (filename, &arg[i]); */ filename = &arg[i]; optused++; if (fileopen){ fclose (outfile); fileopen = 0; } break; case 'p': /* set printer pitch */ ptr.hpitch = atoi (&arg[i]); optused++; break; case 'r': /* set red value */ r_intens = atof (&arg[i]); optused++; break; case 's': /* print sideways option */ sideopt = !sideopt; break; case 't': /* set top edge of screen to print */ scr.ystart = atoi (&arg[i]); optused++; break; case 'u': /* universal printing option (use backspaces) */ universal = 1; break; case 'v': /* view file option */ viewopt = atoi (&arg[i]); autopt = 0; /* turns off auto-printing option */ optused++; break; case 'w': /* set screen width */ scr.width = atoi (&arg[i]); optused++; break; case 'z': /* just print test pattern */ testpat = 1; break; default: printf ("Unknown option %c\n", c); help (documentation); } /* switch (c) */ c = arg[i]; } /* while */ return (0); }else /* Just a file name */ return (1); } /* eval_arg */ /* init_graph: Initialize Amiga graphics */ int init_graph() { if ((GfxBase = OpenLibrary("graphics.library", (long)0)) == NULL){ printf("Can't open Graphics Library\n"); return(1); } if ((LayersBase = OpenLibrary("layers.library", (long)0)) == NULL){ printf("Can't open Layers Library\n"); dwip_cleanup(); return(2); } if ((IntuitionBase = OpenLibrary("intuition.library",(long)0)) == NULL){ printf("Can't open Intuition Library\n"); dwip_cleanup(); return(3); } if ( (DwipScreen = OpenScreen(&DwipNewScreen) ) == NULL){ printf("OpenScreen failed\n"); dwip_cleanup(); return(4); } InitRastPort(&DwipRastPort); DwipRastPort.Mask = (1<bitmap.Depth; for (j=0; j < s_info->bitmap.Depth; j++) bplane[j] = (char *)s_info->bitmap.Planes[j]; fprintf(outfile,"%s", init_string); /* want normal or sideways print? */ if (! sideopt){ /* normal printout */ for (y = scr.ystart, yskip = 0.; y <= scr.ystop; y++){ yskip += 1.; while (yskip > vreduce){ /* plot this line */ yskip -= vreduce; /* Initialize the line buffers */ for (i = 0; i < NBUFS; i++) buf_used[i] = 0; for (x=scr.xstart, xskip=0., ct=0; x <= scr.xstop; x++){ xskip += 1.; while (xskip > hreduce){ /* plot this pixel */ xskip -= hreduce; shade = get_shade (x, y); /* fprintf (outfile, "%s", charshade (shade)); */ outstring (charshade (shade), ct++); #ifdef DEBUG if (ct > ptr.width) printf("Warning: %d chars on line\n", ct); #endif DEBUG } /* while xskip */ } /* for x */ /* print out the buffers */ for (i = 0; i < NBUFS; i++) if (buf_used[i]){ buf[i][ct] = NULL; /* first print the buffer */ fprintf (outfile, "%s", buf[i]); /* Now do something to get printhead back to * beginning of line, for overstriking. */ if (universal) /* Universal printer output sends backspaces * instead of a carriage return. */ for (j = 0; j < ct; j++) fprintf (outfile, "\010"); else /* each buffer followed by carriage return */ fprintf (outfile, "\015"); } /* the end-of-line string */ fprintf(outfile,"%s", eol_string); } /* while yskip */ } /* for y */ }else{ /* sideways print */ for (x = scr.xstart, xskip = 0.; x <= scr.xstop; x++){ xskip += 1.; while (xskip > vreduce){ /* plot this line */ xskip -= vreduce; /* Initialize the line buffers */ for (i = 0; i < NBUFS; i++) buf_used[i] = 0; for (y=scr.ystop, yskip=0., ct=0; y >= scr.ystart; y--){ yskip += 1.; while (yskip > hreduce){ /* plot this pixel */ yskip -= hreduce; shade = get_shade (x, y); /* fprintf (outfile, "%s", charshade (shade)); */ outstring (charshade (shade), ct++); } /* while yskip */ } /* for y */ /* print out the buffers */ for (i = 0; i < NBUFS; i++) if (buf_used[i]){ buf[i][ct] = NULL; /* first print the buffer */ fprintf (outfile, "%s", buf[i]); /* Now do something to get printhead back to * beginning of line, for overstriking. */ if (universal) /* Universal printer output sends backspaces * instead of a carriage return. */ for (j = 0; j < ct; j++) fprintf (outfile, "\010"); else /* each buffer followed by carriage return */ fprintf (outfile, "\015"); } /* the end-of-line string */ fprintf(outfile,"%s", eol_string); } /* while xskip */ } /* for x */ } /* if ! sideopt */ } /* printscreen */ /* eval_env: Evaluate the DWIP environment variable */ void eval_env() { char *getenv(), *index(); int eval_arg(); char *opts; if (opts = getenv ("DWIP")){ while (opts){ if (eval_arg (opts)){ /* eval_arg thinks it's a filename; probably just an extra * space between arguments, so ignore */ opts++; }else{ /* advance to next argument */ opts = index (opts, ' '); if (opts) opts++; } } /* while */ } /* if opts */ } /* eval_env */ /* display_pic: Display an IFF picture on the screen, return 1 if * successful, 0 if not. */ int display_pic (flnm) char *flnm; { void help(), set_values(), free_planes(), put_ea_cmap(); struct ILBM_info *read_iff(); set_values(); if (scrn_alloc){ free_planes (&s_info->bitmap); scrn_alloc = 0; } if ((s_info = read_iff(flnm, 0)) != NULL){ scrn_alloc = 1; put_ea_cmap(&s_info->cmap, (1 << s_info->bitmap.Depth)); DwipRastPort.BitMap = &s_info->bitmap; ClipBlit( &DwipRastPort, (long)0, (long)0, &DwipScreen->RastPort, (long)s_info->header.x, (long)s_info->header.y, (long)s_info->header.w, (long)s_info->header.h, (long)COPY_MINTERM); return (1); }else return (0); } /* display_pic */ /* print_testpat: Print a simple test pattern across the page (5 lines) */ void print_testpat () { char *charshade(); void outstring(); int ct, /* # shades of grey */ l, /* line # */ i, /* buffer # */ j; /* ctr for backspaces */ if (! fileopen){ if ((outfile = fopen (filename, "w")) == NULL){ printf("Couldn't open file %s for output\n", filename); help (documentation); } fileopen = 1; } for (l = 0; l < 5; l++){ /* Initialize the line buffers */ for (i = 0; i < NBUFS; i++) buf_used[i] = 0; /* Output a continuous line of grey (black to white) */ for (ct = 0; ct < MAXSHADES; ct++) outstring (charshade (ct), ct); /* print out the buffers */ for (i = 0; i < NBUFS; i++){ if (buf_used[i]){ buf[i][ct] = NULL; /* first print the buffer */ fprintf (outfile, "%s", buf[i]); /* Now do something to get printhead back to * beginning of line, for overstriking. */ if (universal) /* Universal printer output sends backspaces * instead of a carriage return. */ for (j = 0; j < ct; j++) fprintf (outfile, "\010"); else /* each buffer followed by carriage return */ fprintf (outfile, "\015"); } /* if buf_used */ } /* for i */ /* the end-of-line string */ fprintf(outfile,"%s", eol_string); } /* for l */ } /* print_testpat */ main (argc, argv) int argc; char *argv[]; { int eval_arg(), init_graph(), display_pic(); void eval_env(), dwip_cleanup(), printscreen(), print_testpat(); char *mktemp(); int i, /* index to args */ nfiles = 0; /* # input files read */ filename = mktemp ("RAM:dwXXXX"); eval_env(); /* Initialize graphics */ if (init_graph()){ dwip_cleanup(); exit(1); } /* parse the command line */ for (i=1; ibitmap); scrn_alloc = 0; }else /* if display_pic */ printf("dwip: Couldn't load %s as an IFF file\n", argv[i]); } /* if eval_arg */ } /* for argv */ if (nfiles) dwip_cleanup(); else if (testpat){ print_testpat(); dwip_cleanup(); }else{ printf ("dwip: No files specified.\n"); help (documentation); } #ifdef NEVER /* This didn't work right, so I took it out. Seemed like a nice idea. * If anybody knows what I did wrong, let me know. -kvc */ if (autopt) execlp ("runback", "runback", "c:type", filename, "to", "PRT:",0); #endif NEVER } /* main */