summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/device.h31
-rw-r--r--source/fitz/draw-device.c122
-rw-r--r--source/fitz/output-cbz.c34
-rw-r--r--source/tools/muconvert.c5
4 files changed, 165 insertions, 27 deletions
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index 3a3dd416..02f20ef6 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -357,4 +357,35 @@ fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, const
fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest);
+/*
+ struct fz_draw_options: Options for creating a pixmap and draw device.
+*/
+typedef struct fz_draw_options_s fz_draw_options;
+
+struct fz_draw_options_s
+{
+ int rotate;
+ int resolution;
+ int width;
+ int height;
+ fz_colorspace *colorspace;
+ int alpha;
+};
+
+extern const char *fz_draw_options_usage;
+
+/*
+ fz_parse_draw_options: Parse draw device options from a comma separated key-value string.
+*/
+fz_draw_options *fz_parse_draw_options(fz_context *ctx, fz_draw_options *options, const char *string);
+
+/*
+ fz_new_draw_device_with_options: Create a new pixmap and draw device, using the specified options.
+
+ mediabox: An in parameter containing the size of the page.
+ pixmap: An out parameter containing the newly created pixmap.
+ transform: An out parameter containing the transform to be used when running the page.
+*/
+fz_device *fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, const fz_rect *mediabox, fz_matrix *transform, fz_pixmap **pixmap);
+
#endif
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index d72b20d0..f725fd41 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -1,6 +1,128 @@
#include "mupdf/fitz.h"
#include "draw-imp.h"
+const char *fz_draw_options_usage =
+ "Common raster format output options:\n"
+ "\trotate=N: rotate rendered pages N degrees counterclockwise\n"
+ "\tresolution=N: resolution of rendered pages in pixels per inch\n"
+ "\twidth=N: render pages to fit N pixels wide (ignore resolution option)\n"
+ "\theight=N: render pages to fit N pixels tall (ignore resolution option)\n"
+ "\tcolorspace=(gray|rgb|cmyk): render using specified colorspace\n"
+ "\talpha: render pages with alpha channel and transparent background\n"
+ ;
+
+static int opteq(const char *a, const char *b)
+{
+ int n = strlen(b);
+ return !strncmp(a, b, n) && (a[n] == ',' || a[n] == 0);
+}
+
+fz_draw_options *
+fz_parse_draw_options(fz_context *ctx, fz_draw_options *opts, const char *args)
+{
+ const char *val;
+
+ memset(opts, 0, sizeof *opts);
+
+ opts->resolution = 96;
+ opts->rotate = 0;
+ opts->width = 0;
+ opts->height = 0;
+ opts->colorspace = fz_device_rgb(ctx);
+ opts->alpha = 0;
+
+ if (fz_has_option(ctx, args, "rotate", &val))
+ opts->rotate = fz_atoi(val);
+ if (fz_has_option(ctx, args, "resolution", &val))
+ opts->resolution = fz_atoi(val);
+ if (fz_has_option(ctx, args, "width", &val))
+ opts->width = fz_atoi(val);
+ if (fz_has_option(ctx, args, "height", &val))
+ opts->height = fz_atoi(val);
+ if (fz_has_option(ctx, args, "colorspace", &val))
+ {
+ if (opteq(val, "gray") || opteq(val, "grey"))
+ opts->colorspace = fz_device_gray(ctx);
+ else if (opteq(val, "rgb"))
+ opts->colorspace = fz_device_rgb(ctx);
+ else if (opteq(val, "cmyk"))
+ opts->colorspace = fz_device_cmyk(ctx);
+ else
+ fz_throw(ctx, FZ_ERROR_GENERIC, "unknown colorspace in options");
+ }
+ if (fz_has_option(ctx, args, "alpha", &val))
+ opts->alpha = opteq(val, "yes");
+
+ /* Sanity check values */
+ if (opts->resolution <= 0) opts->resolution = 96;
+ if (opts->width < 0) opts->width = 0;
+ if (opts->height < 0) opts->height = 0;
+
+ return opts;
+}
+
+fz_device *
+fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, const fz_rect *mediabox,
+ fz_matrix *transform, fz_pixmap **pixmap)
+{
+ float zoom = opts->resolution / 72.0f;
+ int w = opts->width;
+ int h = opts->height;
+ fz_rect bounds;
+ fz_irect ibounds;
+ fz_device *dev;
+
+ fz_pre_scale(fz_rotate(transform, opts->rotate), zoom, zoom);
+ bounds = *mediabox;
+ fz_round_rect(&ibounds, fz_transform_rect(&bounds, transform));
+
+ /* If width or height are set, we may need to adjust the transform */
+ if (w || h)
+ {
+ float scalex = 1;
+ float scaley = 1;
+ if (w != 0)
+ scalex = w / (bounds.x1 - bounds.x0);
+ if (h != 0)
+ scaley = h / (bounds.y1 - bounds.y0);
+ if (scalex != scaley)
+ {
+ if (w == 0)
+ scalex = scaley;
+ else if (h == 0)
+ scaley = scalex;
+ else if (scalex > scaley)
+ scalex = scaley;
+ else
+ scaley = scalex;
+ }
+ if (scalex != 1 || scaley != 1)
+ {
+ fz_pre_scale(transform, scalex, scaley);
+ bounds = *mediabox;
+ fz_round_rect(&ibounds, fz_transform_rect(&bounds, transform));
+ }
+ }
+
+ *pixmap = fz_new_pixmap_with_bbox(ctx, opts->colorspace, &ibounds, opts->alpha);
+ fz_try(ctx)
+ {
+ if (opts->alpha)
+ fz_clear_pixmap(ctx, *pixmap);
+ else
+ fz_clear_pixmap_with_value(ctx, *pixmap, 255);
+
+ dev = fz_new_draw_device(ctx, *pixmap);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_pixmap(ctx, *pixmap);
+ *pixmap = NULL;
+ fz_rethrow(ctx);
+ }
+ return dev;
+}
+
#define STACK_SIZE 96
/* Enable the following to attempt to support knockout and/or isolated
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index 4c6d0ca0..ebfded4c 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -8,32 +8,18 @@ struct fz_cbz_writer_s
{
fz_document_writer super;
fz_zip_writer *zip;
- float resolution;
+ fz_draw_options options;
fz_pixmap *pixmap;
int count;
};
-const char *fz_cbz_write_options_usage =
- "CBZ output options:\n"
- "\tresolution=N: resolution of rendered pages in pixels per inch (default 96)\n"
- ;
+const char *fz_cbz_write_options_usage = "";
static fz_device *
-cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox, fz_matrix *ctm)
+cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox, fz_matrix *transform)
{
fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
- fz_rect bbox;
- fz_irect ibbox;
-
- fz_scale(ctm, wri->resolution / 72, wri->resolution / 72);
- bbox = *mediabox;
- fz_transform_rect(&bbox, ctm);
- fz_round_rect(&ibbox, &bbox);
-
- wri->pixmap = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &ibbox, 1);
- fz_clear_pixmap_with_value(ctx, wri->pixmap, 0xFF);
-
- return fz_new_draw_device(ctx, wri->pixmap);
+ return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, transform, &wri->pixmap);
}
static void
@@ -57,6 +43,8 @@ cbz_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
fz_drop_pixmap(ctx, wri->pixmap);
wri->pixmap = NULL;
+
+ fz_drop_device(ctx, dev);
}
static void
@@ -74,7 +62,6 @@ cbz_close(fz_context *ctx, fz_document_writer *wri_)
fz_document_writer *
fz_new_cbz_writer(fz_context *ctx, const char *path, const char *options)
{
- const char *val;
fz_cbz_writer *wri;
wri = fz_malloc_struct(ctx, fz_cbz_writer);
@@ -83,18 +70,15 @@ fz_new_cbz_writer(fz_context *ctx, const char *path, const char *options)
wri->super.close = cbz_close;
fz_try(ctx)
+ {
+ fz_parse_draw_options(ctx, &wri->options, options);
wri->zip = fz_new_zip_writer(ctx, path);
+ }
fz_catch(ctx)
{
fz_free(ctx, wri);
fz_rethrow(ctx);
}
- if (fz_has_option(ctx, options, "resolution", &val))
- wri->resolution = fz_atof(val);
-
- if (wri->resolution <= 0)
- wri->resolution = 96;
-
return (fz_document_writer*)wri;
}
diff --git a/source/tools/muconvert.c b/source/tools/muconvert.c
index 926536fa..8d655bd3 100644
--- a/source/tools/muconvert.c
+++ b/source/tools/muconvert.c
@@ -43,9 +43,10 @@ static void usage(void)
"\tpages\tcomma separated list of page numbers and ranges, where N is the last page\n"
"\n"
);
- fprintf(stderr, "%s\n", fz_cbz_write_options_usage);
+ fprintf(stderr, "%s", fz_draw_options_usage);
+ fprintf(stderr, "%s", fz_cbz_write_options_usage);
#if FZ_ENABLE_PDF
- fprintf(stderr, "%s\n", fz_pdf_write_options_usage);
+ fprintf(stderr, "%s", fz_pdf_write_options_usage);
#endif
exit(1);
}