summaryrefslogtreecommitdiff
path: root/source/fitz/output-ps.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-03-18 16:04:57 +0000
committerRobin Watts <robin.watts@artifex.com>2016-03-21 17:43:39 +0000
commitb20bf99a01d5340e4ad0bd58b1039ac94904bdc4 (patch)
tree82ea8156d3bfd8042edc97613779598c74cd2a0d /source/fitz/output-ps.c
parent51e9b388d1c958a1efa22d712eccd0a4e4d3e2d2 (diff)
downloadmupdf-b20bf99a01d5340e4ad0bd58b1039ac94904bdc4.tar.xz
Add .ps output to mutool draw.
Simple PS wrapped images with flate compression.
Diffstat (limited to 'source/fitz/output-ps.c')
-rw-r--r--source/fitz/output-ps.c198
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);
+}