summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-05-04 18:01:36 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-05-13 11:42:00 +0200
commit0d342fb664c36488bbc0d7f4ca0aa4ab5e7c85b8 (patch)
treefbd7105937e8c2b5b4c8aea8a838b117fb0f8fd5
parent9dda5aa73d6dcb72c9f10b87564afe7491575faf (diff)
downloadmupdf-0d342fb664c36488bbc0d7f4ca0aa4ab5e7c85b8.tar.xz
Add pdf write support to mutool convert.
-rw-r--r--source/fitz/output-cbz.c4
-rw-r--r--source/fitz/writer.c15
-rw-r--r--source/pdf/pdf-write.c94
-rw-r--r--source/tools/muconvert.c91
4 files changed, 184 insertions, 20 deletions
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index d6f1e07c..d9aff180 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -60,7 +60,7 @@ cbz_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
}
static void
-cbz_drop_imp(fz_context *ctx, fz_document_writer *wri_)
+cbz_close(fz_context *ctx, fz_document_writer *wri_)
{
fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
fz_try(ctx)
@@ -80,7 +80,7 @@ fz_new_cbz_writer(fz_context *ctx, const char *path, const char *options)
wri = fz_malloc_struct(ctx, fz_cbz_writer);
wri->super.begin_page = cbz_begin_page;
wri->super.end_page = cbz_end_page;
- wri->super.drop_imp = cbz_drop_imp;
+ wri->super.close = cbz_close;
fz_try(ctx)
wri->zip = fz_new_zip_writer(ctx, path);
diff --git a/source/fitz/writer.c b/source/fitz/writer.c
index b015b5bb..cb4ca77a 100644
--- a/source/fitz/writer.c
+++ b/source/fitz/writer.c
@@ -54,15 +54,26 @@ fz_new_document_writer(fz_context *ctx, const char *path, const char *format, co
if (!fz_strcasecmp(format, "cbz"))
return fz_new_cbz_writer(ctx, path, options);
+ if (!fz_strcasecmp(format, "pdf"))
+ return fz_new_pdf_writer(ctx, path, options);
fz_throw(ctx, FZ_ERROR_GENERIC, "unknown document format: %s", format);
}
void
+fz_close_document_writer(fz_context *ctx, fz_document_writer *wri)
+{
+ if (wri->close)
+ wri->close(ctx, wri);
+ wri->close = NULL;
+ fz_free(ctx, wri);
+}
+
+void
fz_drop_document_writer(fz_context *ctx, fz_document_writer *wri)
{
- if (wri->drop_imp)
- wri->drop_imp(ctx, wri);
+ if (wri->close)
+ wri->close(ctx, wri);
fz_free(ctx, wri);
}
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c
index b4c565cf..5154f818 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -3102,3 +3102,97 @@ void pdf_finish_edit(fz_context *ctx, pdf_document *doc)
return;
pdf_rebalance_page_tree(ctx, doc);
}
+
+typedef struct pdf_writer_s pdf_writer;
+
+struct pdf_writer_s
+{
+ fz_document_writer super;
+ pdf_document *pdf;
+ pdf_write_options opts;
+ char *filename;
+
+ fz_rect mediabox;
+ pdf_obj *resources;
+ fz_buffer *contents;
+};
+
+static fz_device *
+pdf_writer_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox, fz_matrix *ctm)
+{
+ pdf_writer *wri = (pdf_writer*)wri_;
+ wri->mediabox = *mediabox;
+ *ctm = fz_identity;
+ return pdf_page_write(ctx, wri->pdf, &wri->mediabox, &wri->resources, &wri->contents);
+}
+
+static void
+pdf_writer_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
+{
+ pdf_writer *wri = (pdf_writer*)wri_;
+ pdf_obj *obj = NULL;
+
+ fz_var(obj);
+
+ fz_try(ctx)
+ {
+ fz_drop_device(ctx, dev);
+ obj = pdf_add_page(ctx, wri->pdf, &wri->mediabox, 0, wri->resources, wri->contents);
+ pdf_insert_page(ctx, wri->pdf, -1, obj);
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(ctx, obj);
+ fz_drop_buffer(ctx, wri->contents);
+ wri->contents = NULL;
+ pdf_drop_obj(ctx, wri->resources);
+ wri->resources = NULL;
+ }
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
+static void
+pdf_writer_close(fz_context *ctx, fz_document_writer *wri_)
+{
+ pdf_writer *wri = (pdf_writer*)wri_;
+ fz_try(ctx)
+ pdf_save_document(ctx, wri->pdf, wri->filename, &wri->opts);
+ fz_always(ctx)
+ {
+ fz_drop_buffer(ctx, wri->contents);
+ pdf_drop_obj(ctx, wri->resources);
+ pdf_drop_document(ctx, wri->pdf);
+ fz_free(ctx, wri->filename);
+ }
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
+fz_document_writer *
+fz_new_pdf_writer(fz_context *ctx, const char *path, const char *options)
+{
+ pdf_writer *wri;
+
+ wri = fz_malloc_struct(ctx, pdf_writer);
+ wri->super.begin_page = pdf_writer_begin_page;
+ wri->super.end_page = pdf_writer_end_page;
+ wri->super.close = pdf_writer_close;
+
+ fz_try(ctx)
+ {
+ wri->filename = fz_strdup(ctx, path);
+ wri->pdf = pdf_create_document(ctx);
+ }
+ fz_catch(ctx)
+ {
+ pdf_drop_document(ctx, wri->pdf);
+ fz_free(ctx, wri->filename);
+ fz_free(ctx, wri);
+ fz_rethrow(ctx);
+ }
+
+ pdf_parse_write_options(ctx, &wri->opts, options);
+
+ return (fz_document_writer*)wri;
+}
diff --git a/source/tools/muconvert.c b/source/tools/muconvert.c
index 18bbd46b..7c2d1f4f 100644
--- a/source/tools/muconvert.c
+++ b/source/tools/muconvert.c
@@ -20,6 +20,7 @@ static const char *options = "";
static fz_context *ctx;
static fz_document *doc;
static fz_document_writer *out;
+static int count;
static void usage(void)
{
@@ -43,12 +44,80 @@ static void usage(void)
"\n"
);
fprintf(stderr, "%s\n", fz_cbz_write_options_usage);
+ fprintf(stderr, "%s\n", fz_pdf_write_options_usage);
exit(1);
}
+static int isrange(const char *s)
+{
+ while (*s)
+ {
+ if ((*s < '0' || *s > '9') && *s != 'N' && *s != '-' && *s != ',')
+ return 0;
+ s++;
+ }
+ return 1;
+}
+
+static void runpage(int number)
+{
+ fz_matrix ctm;
+ fz_rect mediabox;
+ fz_page *page;
+ fz_device *dev;
+
+ page = fz_load_page(ctx, doc, number - 1);
+ fz_bound_page(ctx, page, &mediabox);
+ dev = fz_begin_page(ctx, out, &mediabox, &ctm);
+ fz_run_page(ctx, page, dev, &ctm, NULL);
+ fz_end_page(ctx, out, dev);
+ fz_drop_page(ctx, page);
+}
+
+static void runrange(char *s)
+{
+ int start, end, i;
+ while (s[0])
+ {
+ if (s[0] == 'N')
+ {
+ start = count;
+ s += 1;
+ }
+ else
+ start = strtol(s, &s, 10);
+
+ if (s[0] == '-')
+ {
+ if (s[1] == 'N')
+ {
+ end = count;
+ s += 2;
+ }
+ else
+ end = strtol(s+1, &s, 10);
+ }
+ else
+ end = start;
+
+ start = fz_clampi(start, 1, count);
+ end = fz_clampi(end, 1, count);
+
+ if (start < end)
+ for (i = start; i <= end; ++i)
+ runpage(i);
+ else
+ for (i = start; i >= end; --i)
+ runpage(i);
+
+ if (s[0] != ',')
+ break;
+ }
+}
+
int muconvert_main(int argc, char **argv)
{
- int i, k, n, c;
+ int i, c;
while ((c = fz_getopt(argc, argv, "p:A:W:H:S:U:o:F:O:")) != -1)
{
@@ -117,22 +186,12 @@ int muconvert_main(int argc, char **argv)
if (!fz_authenticate_password(ctx, doc, password))
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", argv[i]);
fz_layout_document(ctx, doc, layout_w, layout_h, layout_em);
+ count = fz_count_pages(ctx, doc);
- n = fz_count_pages(ctx, doc);
- for (k = 0; k < n; ++k)
- {
- fz_matrix ctm;
- fz_rect mediabox;
- fz_page *page;
- fz_device *dev;
-
- page = fz_load_page(ctx, doc, k);
- fz_bound_page(ctx, page, &mediabox);
- dev = fz_begin_page(ctx, out, &mediabox, &ctm);
- fz_run_page(ctx, page, dev, &ctm, NULL);
- fz_end_page(ctx, out, dev);
- fz_drop_page(ctx, page);
- }
+ if (isrange(argv[i+1]))
+ runrange(argv[++i]);
+ else
+ runrange("1-N");
fz_drop_document(ctx, doc);
}