summaryrefslogtreecommitdiff
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
parent51e9b388d1c958a1efa22d712eccd0a4e4d3e2d2 (diff)
downloadmupdf-b20bf99a01d5340e4ad0bd58b1039ac94904bdc4.tar.xz
Add .ps output to mutool draw.
Simple PS wrapped images with flate compression.
-rw-r--r--include/mupdf/fitz.h1
-rw-r--r--include/mupdf/fitz/output-ps.h28
-rw-r--r--platform/win32/libmupdf.vcproj8
-rw-r--r--source/fitz/output-ps.c198
-rw-r--r--source/tools/mudraw.c21
5 files changed, 254 insertions, 2 deletions
diff --git a/include/mupdf/fitz.h b/include/mupdf/fitz.h
index 60102b67..7ffca1cf 100644
--- a/include/mupdf/fitz.h
+++ b/include/mupdf/fitz.h
@@ -61,6 +61,7 @@ extern "C" {
#include "mupdf/fitz/output-png.h"
#include "mupdf/fitz/output-pwg.h"
#include "mupdf/fitz/output-pcl.h"
+#include "mupdf/fitz/output-ps.h"
#include "mupdf/fitz/output-svg.h"
#include "mupdf/fitz/output-tga.h"
diff --git a/include/mupdf/fitz/output-ps.h b/include/mupdf/fitz/output-ps.h
new file mode 100644
index 00000000..83fdd607
--- /dev/null
+++ b/include/mupdf/fitz/output-ps.h
@@ -0,0 +1,28 @@
+#ifndef MUPDF_FITZ_OUTPUT_PS_H
+#define MUPDF_FITZ_OUTPUT_PS_H
+
+#include "mupdf/fitz/system.h"
+#include "mupdf/fitz/context.h"
+#include "mupdf/fitz/output.h"
+#include "mupdf/fitz/pixmap.h"
+
+typedef struct fz_ps_output_context_s fz_ps_output_context;
+
+/*
+ PS (image) output
+*/
+void fz_write_pixmap_as_ps(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap);
+
+void fz_save_pixmap_as_ps(fz_context *ctx, fz_pixmap *pixmap, char *filename, int append);
+
+void fz_write_ps_file_header(fz_context *ctx, fz_output *out);
+
+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);
+
+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);
+
+void fz_write_ps_trailer(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc);
+
+void fz_write_ps_file_trailer(fz_context *ctx, fz_output *out, int pages);
+
+#endif
diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj
index 3f7cfb69..d56cb947 100644
--- a/platform/win32/libmupdf.vcproj
+++ b/platform/win32/libmupdf.vcproj
@@ -963,6 +963,10 @@
>
</File>
<File
+ RelativePath="..\..\source\fitz\output-ps.c"
+ >
+ </File>
+ <File
RelativePath="..\..\source\fitz\output-pwg.c"
>
</File>
@@ -1510,6 +1514,10 @@
>
</File>
<File
+ RelativePath="..\..\include\mupdf\fitz\output-ps.h"
+ >
+ </File>
+ <File
RelativePath="..\..\include\mupdf\fitz\output-pwg.h"
>
</File>
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);
+}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index bcc67b11..40d01620 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -14,7 +14,7 @@
enum {
OUT_NONE,
OUT_PNG, OUT_TGA, OUT_PNM, OUT_PGM, OUT_PPM, OUT_PAM,
- OUT_PBM, OUT_PKM, OUT_PWG, OUT_PCL,
+ OUT_PBM, OUT_PKM, OUT_PWG, OUT_PCL, OUT_PS,
OUT_TEXT, OUT_HTML, OUT_STEXT,
OUT_TRACE, OUT_SVG, OUT_PDF,
OUT_GPROOF
@@ -40,6 +40,7 @@ static const suffix_t suffix_table[] =
{ ".svg", OUT_SVG },
{ ".pwg", OUT_PWG },
{ ".pcl", OUT_PCL },
+ { ".ps", OUT_PS },
{ ".pdf", OUT_PDF },
{ ".tga", OUT_TGA },
@@ -94,6 +95,7 @@ static const format_cs_table_t format_cs_table[] =
{ OUT_PKM, CS_CMYK, { CS_CMYK } },
{ OUT_PWG, CS_RGB, { CS_MONO, CS_GRAY, CS_RGB, CS_CMYK } },
{ OUT_PCL, CS_MONO, { CS_MONO } },
+ { OUT_PS, CS_RGB, { CS_GRAY, CS_RGB, CS_CMYK } },
{ OUT_TGA, CS_RGB, { CS_GRAY, CS_GRAY_ALPHA, CS_RGB, CS_RGB_ALPHA } },
{ OUT_TRACE, CS_RGB, { CS_RGB } },
@@ -148,6 +150,7 @@ static fz_colorspace *colorspace;
static char *filename;
static int files = 0;
fz_output *out = NULL;
+static int output_pagenum = 0;
static struct {
int count, total;
@@ -166,7 +169,7 @@ static void usage(void)
"\n"
"\t-o -\toutput file name (%%d for page number)\n"
"\t-F -\toutput format (default inferred from output file name)\n"
- "\t\traster: png, tga, pnm, pam, pbm, pkm, pwg, pcl\n"
+ "\t\traster: png, tga, pnm, pam, pbm, pkm, pwg, pcl, ps\n"
"\t\tvector: svg, pdf, trace\n"
"\t\ttext: txt, html, stext\n"
"\n"
@@ -268,6 +271,9 @@ file_level_headers(fz_context *ctx)
if (output_format == OUT_STEXT || output_format == OUT_TRACE)
fz_printf(ctx, out, "<document name=\"%s\">\n", filename);
+
+ if (output_format == OUT_PS)
+ fz_write_ps_file_header(ctx, out);
}
static void
@@ -284,6 +290,9 @@ file_level_trailers(fz_context *ctx)
fz_printf(ctx, out, "</style>\n");
}
+ if (output_format == OUT_PS)
+ fz_write_ps_file_trailer(ctx, out, output_pagenum);
+
fz_drop_stext_sheet(ctx, sheet);
}
@@ -538,9 +547,11 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
fz_pixmap *pix = NULL;
int w, h;
fz_png_output_context *poc = NULL;
+ fz_ps_output_context *psoc = NULL;
fz_var(pix);
fz_var(poc);
+ fz_var(psoc);
fz_bound_page(ctx, page, &bounds);
zoom = resolution / 72;
@@ -637,6 +648,8 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
fz_write_pbm_header(ctx, out, pix->w, totalheight);
else if (output_format == OUT_PKM)
fz_write_pkm_header(ctx, out, pix->w, totalheight);
+ else if (output_format == OUT_PS)
+ psoc = fz_write_ps_header(ctx, out, pix->w, totalheight, pix->n, pix->xres, pix->yres, ++output_pagenum);
}
for (band = 0; band < bands; band++)
@@ -689,6 +702,8 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
else
fz_write_pixmap_as_pcl(ctx, out, pix, &options);
}
+ else if (output_format == OUT_PS)
+ fz_write_ps_band(ctx, out, psoc, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
else if (output_format == OUT_PBM) {
fz_bitmap *bit = fz_new_bitmap_from_pixmap_band(ctx, pix, NULL, band, bandheight);
fz_write_pbm_band(ctx, out, bit);
@@ -723,6 +738,8 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
{
if (output_format == OUT_PNG)
fz_write_png_trailer(ctx, out, poc);
+ if (output_format == OUT_PS)
+ fz_write_ps_trailer(ctx, out, psoc);
}
}
fz_always(ctx)