diff options
author | Robin Watts <robin.watts@artifex.com> | 2016-03-18 16:04:57 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2016-03-21 17:43:39 +0000 |
commit | b20bf99a01d5340e4ad0bd58b1039ac94904bdc4 (patch) | |
tree | 82ea8156d3bfd8042edc97613779598c74cd2a0d /source/fitz | |
parent | 51e9b388d1c958a1efa22d712eccd0a4e4d3e2d2 (diff) | |
download | mupdf-b20bf99a01d5340e4ad0bd58b1039ac94904bdc4.tar.xz |
Add .ps output to mutool draw.
Simple PS wrapped images with flate compression.
Diffstat (limited to 'source/fitz')
-rw-r--r-- | source/fitz/output-ps.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/source/fitz/output-ps.c b/source/fitz/output-ps.c new file mode 100644 index 00000000..35c0a333 --- /dev/null +++ b/source/fitz/output-ps.c @@ -0,0 +1,198 @@ +#include "mupdf/fitz.h" + +#include <zlib.h> + +struct fz_ps_output_context_s +{ + z_stream stream; + int input_size; + unsigned char *input; + int output_size; + unsigned char *output; +}; + +void +fz_write_ps_file_header(fz_context *ctx, fz_output *out) +{ + fz_printf(ctx, out, + "%%!PS-Adobe-3.0\n" + //"%%%%BoundingBox: 0 0 612 792\n" + //"%%%%HiResBoundingBox: 0 0 612 792\n" + "%%%%Creator: MuPDF\n" + "%%%%LanguageLevel: 2\n" + "%%%%CreationDate: D:20160318101706Z00'00'\n" + "%%%%DocumentData: Binary\n" + "%%%%Pages: (atend)\n" + "%%%%EndComments\n" + "\n" + "%%%%BeginProlog\n" + "%%%%EndProlog\n" + "\n" + "%%%%BeginSetup\n" + "%%%%EndSetup\n" + "\n" + ); +} + +void fz_write_ps_file_trailer(fz_context *ctx, fz_output *out, int pages) +{ + fz_printf(ctx, out, "%%%%Trailer\n%%%%Pages: %d\n%%%%EOF\n", pages); +} + +fz_ps_output_context *fz_write_ps_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum) +{ + int w_points = (w * 72 + (xres>>1)) / xres; + int h_points = (h * 72 + (yres>>1)) / yres; + float sx = w/(float)w_points; + float sy = h/(float)h_points; + fz_ps_output_context *psoc; + int err; + + psoc = fz_malloc_struct(ctx, fz_ps_output_context); + err = deflateInit(&psoc->stream, Z_DEFAULT_COMPRESSION); + if (err != Z_OK) + { + fz_free(ctx, psoc); + fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err); + } + + fz_printf(ctx, out, "%%%%Page: %d %d\n", pagenum, pagenum); + fz_printf(ctx, out, "%%%%PageBoundingBox: 0 0 %d %d\n", w_points, h_points); + fz_printf(ctx, out, "%%%%BeginPageSetup\n"); + fz_printf(ctx, out, "<</PageSize [%d %d]>> setpagedevice\n", w_points, h_points); + fz_printf(ctx, out, "%%%%EndPageSetup\n\n"); + fz_printf(ctx, out, "/DataFile currentfile /FlateDecode filter def\n\n"); + switch(n) + { + case 2: + fz_printf(ctx, out, "/DeviceGray setcolorspace\n"); + break; + case 4: + fz_printf(ctx, out, "/DeviceRGB setcolorspace\n"); + break; + case 5: + fz_printf(ctx, out, "/DeviceCMYK setcolorspace\n"); + break; + default: + fz_throw(ctx, FZ_ERROR_GENERIC, "Unexpected colorspace for ps output"); + } + fz_printf(ctx, out, + "<<\n" + "/ImageType 1\n" + "/Width %d\n" + "/Height %d\n" + "/ImageMatrix [ %f 0 0 -%f 0 %d ]\n" + "/MultipleDataSources false\n" + "/DataSource DataFile\n" + "/BitsPerComponent 8\n" + //"/Decode [0 1]\n" + "/Interpolate false\n" + ">>\n" + "image\n" + , w, h, sx, sy, h); + + return psoc; +} + +void fz_write_ps_trailer(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc) +{ + if (psoc) + { + int err; + + psoc->stream.next_in = NULL; + psoc->stream.avail_in = 0; + psoc->stream.next_out = (Bytef*)psoc->output; + psoc->stream.avail_out = (uInt)psoc->output_size; + + err = deflate(&psoc->stream, Z_FINISH); + if (err != Z_STREAM_END) + fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err); + + fz_write(ctx, out, psoc->output, psoc->output_size - psoc->stream.avail_out); + fz_free(ctx, psoc->input); + fz_free(ctx, psoc->output); + fz_free(ctx, psoc); + } + fz_printf(ctx, out, "\nshowpage\n%%%%PageTrailer\n%%%%EndPageTrailer\n\n"); + +} + +void fz_write_pixmap_as_ps(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap) +{ + fz_ps_output_context *psoc; + + fz_write_ps_file_header(ctx, out); + + psoc = fz_write_ps_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->xres, pixmap->yres, 1); + + fz_try(ctx) + { + fz_write_ps_band(ctx, out, psoc, pixmap->w, pixmap->h, pixmap->n, 0, 0, pixmap->samples); + } + fz_always(ctx) + { + fz_write_ps_trailer(ctx, out, psoc); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + fz_write_ps_file_trailer(ctx, out, 1); +} + +void fz_save_pixmap_as_ps(fz_context *ctx, fz_pixmap *pixmap, char *filename, int append) +{ + fz_output *out = fz_new_output_with_path(ctx, filename, append); + fz_try(ctx) + fz_write_pixmap_as_ps(ctx, out, pixmap); + fz_always(ctx) + fz_drop_output(ctx, out); + fz_catch(ctx) + fz_rethrow(ctx); +} + +void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int band, int bandheight, unsigned char *samples) +{ + int x, y, i, err; + int required_input = w*(n-1)*h; + int required_output = (int)deflateBound(&psoc->stream, required_input); + unsigned char *o; + + if (psoc->input == NULL || psoc->input_size < required_input) + { + fz_free(ctx, psoc->input); + psoc->input = NULL; + psoc->input = fz_malloc(ctx, required_input); + psoc->input_size = required_input; + } + + if (psoc->output == NULL || psoc->output_size < required_output) + { + fz_free(ctx, psoc->output); + psoc->output = NULL; + psoc->output = fz_malloc(ctx, required_output); + psoc->output_size = required_output; + } + + o = psoc->input; + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + { + for (i = n-1; i > 0; i--) + *o++ = *samples++; + samples++; + } + + psoc->stream.next_in = (Bytef*)psoc->input; + psoc->stream.avail_in = required_input; + psoc->stream.next_out = (Bytef*)psoc->output; + psoc->stream.avail_out = (uInt)psoc->output_size; + + err = deflate(&psoc->stream, Z_NO_FLUSH); + if (err != Z_OK) + fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err); + + fz_write(ctx, out, psoc->output, psoc->output_size - psoc->stream.avail_out); +} |