/* *---------------------------------------------------------------------- * plotHP.c -- * * This file contains the procedures that generate plots in * HP Raster Transfer Language (HPRTL) and HPGL2. * *---------------------------------------------------------------------- */ #include #include #include #include "utils/malloc.h" #include "plot/plotInt.h" /* C99 compat */ #include "textio/textio.h" #ifdef VERSATEC extern int PlotRTLCompress(); extern void PlotHPRTLTrailer(); extern int rasFileByteCount; /* * ---------------------------------------------------------------------------- * * PlotHPRTLHeader -- * * Header for HP RTL format (standard for, e.g., HP color laser printers) * * ---------------------------------------------------------------------------- */ void PlotHPRTLHeader(width, height, density, hpfile) int width, height, density; FILE *hpfile; { fprintf(hpfile, "\033*r-3U\n"); /* Simple CMY color space */ fprintf(hpfile, "\033*r%dS", width); /* Image width in pixels. */ fprintf(hpfile, "\033*r%dT", height); /* Image height in pixels.*/ fprintf(hpfile, "\033&a1N"); /* No negative motion. */ fprintf(hpfile, "\033*b2M"); /* Mode 2 row compression */ fprintf(hpfile, "\033*t%dR", density); /* Plotting density in DPI. */ fprintf(hpfile, "\033*r0A"); /* Start raster data. */ } /* * ---------------------------------------------------------------------------- * * PlotHPGL2Header -- * * Header for HPGL2 (plotter) format * * ---------------------------------------------------------------------------- */ #define LABEL_SPACER 200 /* Height of the label area, in pixels */ #define IN_TO_HPGL 1016 /* HPGL2 coordinates are in 0.025mm units */ #define THIN_MARGIN 40 /* thin spacer (1mm) in HPGL2 coordinates */ void PlotHPGL2Header(width, height, density, scale, hpfile) int width, height, density, scale; FILE *hpfile; { fprintf(hpfile, "\033%%-12345X"); /* Universal Command Language. */ fprintf(hpfile, "@PJL ENTER LANGUAGE=HPGL2\r\n"); fprintf(hpfile, "\033E\033%%0B"); /* Reset printer; set HPGL2 mode. */ fprintf(hpfile, "BP1,\"MAGIC\",5,1;"); /* Declare name; disable auto-rotate */ fprintf(hpfile, "PS%d,%d;", ((height + LABEL_SPACER) * IN_TO_HPGL / density) + THIN_MARGIN, (width * IN_TO_HPGL / density) + THIN_MARGIN); /* Move the pen to the right edge of the paper. */ fprintf(hpfile, "SP1PA%d,0", (width * IN_TO_HPGL / density)); /* Plot upside down with a 10-point font. */ fprintf(hpfile, "DI-1,0SD3,10;"); /* Plot a label. */ fprintf(hpfile, "LB\r\nMagic Plot (%dX)\r\n\003SP0;", scale); fprintf(hpfile, "\033%%0A"); /* Enter RTL mode. */ fprintf(hpfile, "\033*v1N"); /* Source mode opaque */ /* Make room for the label string by moving vertically. */ fprintf(hpfile, "\033*b%dY", LABEL_SPACER); /* HPRTL Color reference guide: */ /* h20000.www2.hp.com/bc/docs/support/SupportManual/bpl13212/bpl13212.pdf */ /* Configure Image Data (CID) command */ /* Color space (1) = CMY */ /* Pixel encoding mode (0) = Index by plane */ /* Bits per index (3) = 8-index (2^3) colormap */ /* Color planes (1, 1, 1) = 1 bit each */ /* Bit planes are cyan / magenta / yellow and must */ /* be output in that order. */ /* fwrite("\033*v6W\1\0\3\1\1\1", 11, 1, hpfile); */ /* Apparently some plotters don't support plane-indexed CMY mode. */ /* Due to this oversight, it is necessary to build the CMY color */ /* table by hand by reversing the RGB color table. */ fwrite("\033*v6W\0\0\3\1\1\1", 11, 1, hpfile); fprintf(hpfile, "\033*v255a255b255c0I\n"); fprintf(hpfile, "\033*v0a255b255c1I\n"); fprintf(hpfile, "\033*v255a0b255c2I\n"); fprintf(hpfile, "\033*v0a0b255c3I\n"); fprintf(hpfile, "\033*v255a255b0c4I\n"); fprintf(hpfile, "\033*v0a255b0c5I\n"); fprintf(hpfile, "\033*v255a0b0c6I\n"); fprintf(hpfile, "\033*v0a0b0c7I\n"); fprintf(hpfile, "\033*r%dS", width); /* Set the image width in pixels. */ fprintf(hpfile, "\033*r%dT", height); /* Set the image height in pixels.*/ fprintf(hpfile, "\033&a1N"); /* No negative motion. */ fprintf(hpfile, "\033*b2M"); /* Mode 2 row compression */ fprintf(hpfile, "\033*t%dR", density); /* Plot density, in DPI. */ fprintf(hpfile, "\033*r1A"); /* Start sending raster data. */ } /* * ---------------------------------------------------------------------------- * * PlotHPRTLTrailer -- * * ---------------------------------------------------------------------------- */ void PlotHPRTLTrailer(hpfile) FILE *hpfile; { fprintf(hpfile, "\033*r0B\014\n"); /* End raster graphics. */ } /* * ---------------------------------------------------------------------------- * * PlotHPGL2Trailer -- * * ---------------------------------------------------------------------------- */ void PlotHPGL2Trailer(hpfile) FILE *hpfile; { fprintf(hpfile, "\033*rC"); /* End raster graphics. */ fprintf(hpfile, "\033%%0B"); /* HPGL2 mode. */ fprintf(hpfile, "PG;"); /* Terminate plot. */ fprintf(hpfile, "\033%%-12345X"); /* Universal command language reset. */ fprintf(hpfile, "@PJL\r\n"); } /* * ---------------------------------------------------------------------------- * HP Run-length compression algorithm #2 * This code has been taken from the "p3" PNM-to-HPRTL conversion tool. * Subroutine written by Noel Gorelick (ngorelic@speclab.cr.usgs.gov) * Author's comments below: * * The HP Paintjet 300-XL and DesignJet 650C both have the option of receiving * data using TIFF packbits encoding. This seemed like a good idea to me, so I * ran to the libtiff package to see if there was anything useful there to do * packbits for me. I was sorely disappointed to find a large (225 lines) * routine that will do this, but replys heavily on the internal data * structures used by the rest of the libtiff library. * * So, I wrote my own. Here is a much simpler pair of routines to do the same * thing. These were tested on both the PaintJet-300XL and DesignJet 650C, * having been compiled using an HP9000s800. If anyone is actually interested * in the driver program that converts a PPM image for use on these printers, I * could probably post that as well. * * Noel (ngorelic@speclab.cr.usgs.gov) *----------------------------------------------------------------------- */ /* *----------------------------------------------------------------------- * * PlotRTLCompress -- * * This routine encodes a string using the TIFF packbits encoding * scheme. This encoding method is used by several HP peripherals to * reduce the size of incoming raster images. Both routines convert s1 * into s2. The len parameter indicates the size of the incoming string. * The return value is the size of the output string (in s2). * * Results: * Returns the length of the compressed data. Note that compression * is not guaranteed, and the output may be larger than the input. * However, it is bounded by N + (N / 127) + 1. * * Side effects: * Output data placed in s2, which must be large enough to hold it. * *----------------------------------------------------------------------- */ int PlotRTLCompress(s1, s2, len) unsigned char *s1, *s2; int len; { /* * Pack s1 using TIFF packbits encoding into s2 */ int count = 0; int i; int base, newbase, size, outp; base = newbase = outp = 0; for (i = 1; i < len; i++) { if (s1[newbase] == s1[i]) count++; else { if (count < 2) { newbase = i; count = 0; } else { /* * Put any backed up literals first. */ while ((newbase - base) > 0) { size = MIN(127, newbase - base - 1); s2[outp++] = size; memcpy(s2 + outp, s1 + base, size + 1); outp += size + 1; base += size + 1; } /* * Now put -count and repeated string. */ count++; while (count > 0) { size = MIN(128, count); s2[outp++] = -(size - 1); s2[outp++] = s1[newbase]; count -= size; } base = newbase = i; } } } /* * Output any trailing literals. */ newbase = i; while ((newbase - base) > 0) { size = MIN(127, newbase - base - 1); s2[outp++] = size; memcpy(s2 + outp, s1 + base, size + 1); outp += size + 1; base += size + 1; } return (outp); } /* * ---------------------------------------------------------------------------- * * PlotDumpHPRTL -- * * Combines the four (CMYK) swath buffers by ORing the black image * into the primary color swaths. The swath is compressed using * HP run-length row compression mode 2 (TIFF compression). * * Results: * Returns 0 if all was well. Returns non-zero if there was * an I/O error. In this event, this procedure prints an * error message before returning. * * Side effects: * Information is added to the file. * * ---------------------------------------------------------------------------- */ int PlotDumpHPRTL(hpfile, kRaster, cRaster, mRaster, yRaster) FILE *hpfile; /* File in which to dump it. */ Raster *kRaster; /* Rasters to be dumped. */ Raster *cRaster; Raster *mRaster; Raster *yRaster; { int line, count, line_offset = 0; int ipl, bpl; register int *c, *m, *y, *k; unsigned char *obytes; /* bytes to output (compressed) */ int size; ipl = kRaster->ras_intsPerLine; bpl = kRaster->ras_bytesPerLine; c = cRaster->ras_bits; m = mRaster->ras_bits; y = yRaster->ras_bits; k = kRaster->ras_bits; /* Mode 2 row compression has a worst-case length of N + (N / 127) + 1 */ obytes = (unsigned char *)mallocMagic(bpl + (bpl / 127) + 1); for (line = 0; line < kRaster->ras_height; line++) { /* Merge the black plane into C, M, and Y */ for (count = 0; count < ipl; count++) { *c = (*c | *k); *m = (*m | *k); *y = (*y | *k); c++; m++; y++; k++; } /* Compress each plane (C, M, and Y) and output */ size = PlotRTLCompress((unsigned char *)(c - ipl), obytes, bpl); fprintf(hpfile, "\033*b%dV", size); fwrite(obytes, size, 1, hpfile); size = PlotRTLCompress((unsigned char *)(m - ipl), obytes, bpl); fprintf(hpfile, "\033*b%dV", size); fwrite(obytes, size, 1, hpfile); size = PlotRTLCompress((unsigned char *)(y - ipl), obytes, bpl); fprintf(hpfile, "\033*b%dW", size); fwrite(obytes, size, 1, hpfile); } freeMagic(obytes); if (count < 0) { TxError("I/O error in writing HPRTL file: %s.\n", strerror(errno)); return 1; } rasFileByteCount += count; return 0; } #endif /* VERSATEC */