diff options
-rw-r--r-- | include/mupdf/fitz.h | 1 | ||||
-rw-r--r-- | include/mupdf/fitz/output-ps.h | 28 | ||||
-rw-r--r-- | platform/win32/libmupdf.vcproj | 8 | ||||
-rw-r--r-- | source/fitz/output-ps.c | 198 | ||||
-rw-r--r-- | source/tools/mudraw.c | 21 |
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) |