1 /*
2 * PDF merge tool: Tool for merging pdf content.
3 *
4 * Simple test bed to work with merging pages from multiple PDFs into a single PDF.
5 */
6
7 #include "mupdf/fitz.h"
8 #include "mupdf/pdf.h"
9
10 #include <stdlib.h>
11 #include <stdio.h>
12
usage(void)13 static void usage(void)
14 {
15 fprintf(stderr,
16 "usage: mutool merge [-o output.pdf] [-O options] input.pdf [pages] [input2.pdf] [pages2] ...\n"
17 "\t-o -\tname of PDF file to create\n"
18 "\t-O -\tcomma separated list of output options\n"
19 "\tinput.pdf\tname of input file from which to copy pages\n"
20 "\tpages\tcomma separated list of page numbers and ranges\n\n"
21 );
22 fputs(fz_pdf_write_options_usage, stderr);
23 exit(1);
24 }
25
26 static fz_context *ctx = NULL;
27 static pdf_document *doc_des = NULL;
28 static pdf_document *doc_src = NULL;
29
page_merge(int page_from,int page_to,pdf_graft_map * graft_map)30 static void page_merge(int page_from, int page_to, pdf_graft_map *graft_map)
31 {
32 pdf_graft_mapped_page(ctx, graft_map, page_to - 1, doc_src, page_from - 1);
33 }
34
merge_range(const char * range)35 static void merge_range(const char *range)
36 {
37 int start, end, i, count;
38 pdf_graft_map *graft_map;
39
40 count = pdf_count_pages(ctx, doc_src);
41 graft_map = pdf_new_graft_map(ctx, doc_des);
42
43 fz_try(ctx)
44 {
45 while ((range = fz_parse_page_range(ctx, range, &start, &end, count)))
46 {
47 if (start < end)
48 for (i = start; i <= end; ++i)
49 page_merge(i, -1, graft_map);
50 else
51 for (i = start; i >= end; --i)
52 page_merge(i, -1, graft_map);
53 }
54 }
55 fz_always(ctx)
56 {
57 pdf_drop_graft_map(ctx, graft_map);
58 }
59 fz_catch(ctx)
60 {
61 fz_rethrow(ctx);
62 }
63 }
64
pdfmerge_main(int argc,char ** argv)65 int pdfmerge_main(int argc, char **argv)
66 {
67 pdf_write_options opts = pdf_default_write_options;
68 char *output = "out.pdf";
69 char *flags = "";
70 char *input;
71 int c;
72
73 while ((c = fz_getopt(argc, argv, "o:O:")) != -1)
74 {
75 switch (c)
76 {
77 case 'o': output = fz_optarg; break;
78 case 'O': flags = fz_optarg; break;
79 default: usage(); break;
80 }
81 }
82
83 if (fz_optind == argc)
84 usage();
85
86 ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
87 if (!ctx)
88 {
89 fprintf(stderr, "error: Cannot initialize MuPDF context.\n");
90 exit(1);
91 }
92
93 pdf_parse_write_options(ctx, &opts, flags);
94
95 fz_try(ctx)
96 {
97 doc_des = pdf_create_document(ctx);
98 }
99 fz_catch(ctx)
100 {
101 fprintf(stderr, "error: Cannot create destination document.\n");
102 fz_flush_warnings(ctx);
103 fz_drop_context(ctx);
104 exit(1);
105 }
106
107 /* Step through the source files */
108 while (fz_optind < argc)
109 {
110 doc_src = NULL;
111 input = argv[fz_optind++];
112
113 fz_try(ctx)
114 {
115 doc_src = pdf_open_document(ctx, input);
116 if (fz_optind == argc || !fz_is_page_range(ctx, argv[fz_optind]))
117 merge_range("1-N");
118 else
119 merge_range(argv[fz_optind++]);
120 }
121 fz_always(ctx)
122 pdf_drop_document(ctx, doc_src);
123 fz_catch(ctx)
124 fprintf(stderr, "error: Cannot merge document '%s'.\n", input);
125 }
126
127 if (fz_optind == argc)
128 {
129 fz_try(ctx)
130 pdf_save_document(ctx, doc_des, output, &opts);
131 fz_catch(ctx)
132 fprintf(stderr, "error: Cannot save output file: '%s'.\n", output);
133 }
134
135 pdf_drop_document(ctx, doc_des);
136 fz_flush_warnings(ctx);
137 fz_drop_context(ctx);
138 return 0;
139 }
140