diff options
Diffstat (limited to 'imageto/out-epsf.c')
-rw-r--r-- | imageto/out-epsf.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/imageto/out-epsf.c b/imageto/out-epsf.c new file mode 100644 index 0000000..564807c --- /dev/null +++ b/imageto/out-epsf.c @@ -0,0 +1,166 @@ +/* out-epsf.c: output the whole image as an EPS file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "hexify.h" +#include "report.h" + +#include "main.h" +#include "out-epsf.h" + +extern string version_string; + +static void pack_scanline (one_byte *, unsigned); + +/* Abbreviations for output to `eps_file'. */ +#define OUT_STRING(s) fprintf (eps_file, "%s", s) +#define OUT_SIMPLE(s) fprintf (eps_file, "%%%%%s\n", s) +#define OUT_COMMENT(s, v) fprintf (eps_file, "%%%%%s: %s\n", s, v) +#define OUT1(s, v1) fprintf (eps_file, s, v1) +#define OUT2(s, v1, v2) fprintf (eps_file, s, v1, v2) +#define OUT3(s, v1, v2, v3) fprintf (eps_file, s, v1, v2, v3) + +/* Write an Encapsulated PostScript file corresponding to the image. */ + +void +write_epsf (string output_name, image_header_type image_header) +{ + /* Just black & white, or do we have grayscale? */ + boolean monochrome_p = image_header.depth == 1; + + /* Just for convenience. */ + unsigned width = image_header.width; + unsigned height = image_header.height; + + /* We pack the image tightly if it's monochrome. */ + unsigned width_used = monochrome_p ? width / 8 + !!(width % 8) : width; + + /* Buffer into which we'll read the image data. */ + unsigned scanline_count = 0; + one_byte *scanline = xmalloc (width); + + /* Open the output file OUTPUT_NAME. */ + FILE *eps_file = xfopen (output_name, "w"); + + OUT_STRING ("%!PS-Adobe-3.0 EPSF-3.0\n"); + OUT2 ("%%%%BoundingBox: 0 0 %u %u\n", width, height); + OUT_COMMENT ("Creator", version_string); + OUT_COMMENT ("Title", output_name); + OUT_COMMENT ("CreationDate", now ()); + OUT_COMMENT ("DocumentData", "Clean7Bit"); + OUT_SIMPLE ("EndComments"); + + /* We map the image to the unit square for image(mask) and scale the + coordinate system to get back to the original size. I can't grasp + how to use the matrix argument to image(mask) to avoid the scaling, + but I'm sure it's possible. */ + OUT2 ("gsave\n %u %u scale\n", width, height); + + /* We need a buffer to hold the string chunks as we read them. It + can't be of arbitrary size: it must be an exact multiple of the + total number of data characters. Otherwise, we will read past the + end of the data. */ + OUT1 ("/image-buffer %u string def\n", width_used); + + /* If we are monochrome, we use the `imagemask' operator; else `image'. */ + OUT2 (" %u %u", width, height); + + if (monochrome_p) + OUT_STRING (" true"); /* The `invert' argument. */ + else + OUT1 (" %u", image_header.depth); /* bits/sample */ + + OUT3 (" [%u 0 0 -%u 0 %u]\n", width, height, height); + OUT_STRING ("{currentfile image-buffer readhexstring pop}\n"); + OUT1 ("%s\n", monochrome_p ? "imagemask" : "image"); + + /* Read the image. */ + while ((*image_get_scanline) (scanline)) + { + string h; + unsigned loc; + + scanline_count++; + if (scanline_count % 10 == 0) + REPORT1 (".%s", scanline_count % 790 == 0 ? "\n" : ""); + + /* Monochrome images are output with eight samples/byte; grayscale + images are output with one sample/byte. */ + if (monochrome_p) + pack_scanline (scanline, width); + + /* Convert binary to ASCII hexadecimal. */ + h = hexify (scanline, width_used); + + /* Adobe says lines in EPS files should be no more than 255 + characters. How silly. */ + for (loc = 1; loc <= 2 * width_used; loc++) + { + putc (h[loc - 1], eps_file); + if (loc % 255 == 0) + putc ('\n', eps_file); + } + + free (h); + putc ('\n', eps_file); + } + + /* Restore the ctm. */ + OUT_STRING ("grestore\n"); + + if (scanline_count != image_header.height) + WARNING2 ("Expected %u scanlines, read %u", image_header.height, + scanline_count); + + OUT_SIMPLE ("TRAILER"); + OUT_SIMPLE ("EOF"); +} + +/* Change the one bit/byte representation (call each byte a `cell') of + LENGTH bits in DATA to be eight bits/byte. Pad the last byte with + zero. We don't change those bytes beyond the end of packed portion, + thus assuming they are not looked at. */ + +static void +pack_scanline (one_byte *data, unsigned length) +{ + unsigned cell; /* Which bit in the original data we're on. */ + unsigned packing_loc = 0; /* Which byte we're currently packing. */ + unsigned packing_bit = 8; /* How much to shift. */ + + /* The very first cell has to be treated specially, because we must + initialize it with itself shifted left (if we're going to use data + in place, that is.) */ + data[0] <<= 7; + + for (cell = 0; cell < length; cell++) + { + packing_bit--; + data[packing_loc] |= data[cell] << packing_bit; + if (packing_bit == 0) + { + packing_bit = 8; + packing_loc++; + + /* After the first byte, we can just clear the byte at + `packing_loc', since `cell' has already moved beyond it. */ + data[packing_loc] = 0; + } + } +} |