Skip to content

Commit 71d33c0

Browse files
committed
Add PDF merge example.
1 parent cfe91b4 commit 71d33c0

File tree

3 files changed

+154
-1
lines changed

3 files changed

+154
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
/examples/md2pdf
1717
/examples/pdf2text
1818
/examples/pdfioinfo
19+
/examples/pdfiomerge
1920
/Makefile
2021
/packages
2122
/pdfio.pc

examples/Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ TARGETS = \
2424
image2pdf \
2525
md2pdf \
2626
pdf2text \
27-
pdfioinfo
27+
pdfioinfo \
28+
pdfiomerge
2829

2930

3031
# Make everything
@@ -61,5 +62,10 @@ pdfioinfo: pdfioinfo.c
6162
$(CC) $(CFLAGS) -o $@ pdfioinfo.c $(LIBS)
6263

6364

65+
# pdfiomerge
66+
pdfiomerge: pdfiomerge.c
67+
$(CC) $(CFLAGS) -o $@ pdfiomerge.c $(LIBS)
68+
69+
6470
# Common dependencies...
6571
$(TARGETS): Makefile ../pdfio.h ../pdfio-content.h

examples/pdfiomerge.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//
2+
// PDF merge program for PDFio.
3+
//
4+
// Copyright © 2025 by Michael R Sweet.
5+
//
6+
// Licensed under Apache License v2.0. See the file "LICENSE" for more
7+
// information.
8+
//
9+
// Usage:
10+
//
11+
// ./pdfmerge [-o OUTPUT.pdf] INPUT.pdf [... INPUT.pdf]
12+
// ./pdfmerge INPUT.pdf [... INPUT.pdf] >OUTPUT.pdf
13+
//
14+
15+
#include <pdfio.h>
16+
#include <string.h>
17+
18+
19+
//
20+
// Local functions...
21+
//
22+
23+
static ssize_t output_cb(void *output_cbdata, const void *buffer, size_t bytes);
24+
static int usage(FILE *out);
25+
26+
27+
//
28+
// 'main()' - Main entry.
29+
//
30+
31+
int // O - Exit status
32+
main(int argc, // I - Number of command-line arguments
33+
char *argv[]) // I - Command-line arguments
34+
{
35+
int i; // Looping var
36+
const char *opt; // Current option
37+
pdfio_file_t *inpdf, // Input PDF file
38+
*outpdf = NULL; // Output PDF file
39+
40+
41+
// Parse command-line...
42+
for (i = 1; i < argc; i ++)
43+
{
44+
if (!strcmp(argv[i], "--help"))
45+
{
46+
return (usage(stdout));
47+
}
48+
else if (!strncmp(argv[i], "--", 2))
49+
{
50+
fprintf(stderr, "pdfmerge: Unknown option '%s'.\n", argv[i]);
51+
return (usage(stderr));
52+
}
53+
else if (argv[i][0] == '-')
54+
{
55+
for (opt = argv[i] + 1; *opt; opt ++)
56+
{
57+
switch (*opt)
58+
{
59+
case 'o' : // -o OUTPUT.pdf
60+
if (outpdf)
61+
{
62+
fputs("pdfmerge: Only one output file can be specified.\n", stderr);
63+
return (usage(stderr));
64+
}
65+
66+
i ++;
67+
if (i >= argc)
68+
{
69+
fputs("pdfmerge: Missing output filename after '-o'.\n", stderr);
70+
return (usage(stderr));
71+
}
72+
73+
if ((outpdf = pdfioFileCreate(argv[i], /*version*/NULL, /*media_box*/NULL, /*crop_box*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL)
74+
return (1);
75+
break;
76+
77+
default :
78+
fprintf(stderr, "pdfmerge: Unknown option '-%c'.\n", *opt);
79+
return (usage(stderr));
80+
}
81+
}
82+
}
83+
else if ((inpdf = pdfioFileOpen(argv[i], /*password_cb*/NULL, /*password_data*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL)
84+
{
85+
return (1);
86+
}
87+
else
88+
{
89+
// Copy PDF file...
90+
size_t p, // Current page
91+
nump; // Number of pages
92+
93+
if (!outpdf)
94+
{
95+
if ((outpdf = pdfioFileCreateOutput(output_cb, /*output_cbdata*/NULL, /*version*/NULL, /*media_box*/NULL, /*crop_box*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL)
96+
return (1);
97+
}
98+
99+
for (p = 0, nump = pdfioFileGetNumPages(inpdf); p < nump; p ++)
100+
{
101+
if (!pdfioPageCopy(outpdf, pdfioFileGetPage(inpdf, p)))
102+
return (1);
103+
}
104+
105+
pdfioFileClose(inpdf);
106+
}
107+
}
108+
109+
if (!outpdf)
110+
return (usage(stderr));
111+
112+
pdfioFileClose(outpdf);
113+
114+
return (0);
115+
}
116+
117+
118+
//
119+
// 'output_cb()' - Write PDF data to the standard output...
120+
//
121+
122+
static ssize_t // O - Number of bytes written
123+
output_cb(void *output_cbdata, // I - Callback data (not used)
124+
const void *buffer, // I - Buffer to write
125+
size_t bytes) // I - Number of bytes to write
126+
{
127+
(void)output_cbdata;
128+
129+
return ((ssize_t)fwrite(buffer, 1, bytes, stdout));
130+
}
131+
132+
133+
//
134+
// 'usage()' - Show program usage.
135+
//
136+
137+
static int // O - Exit status
138+
usage(FILE *out) // I - stdout or stderr
139+
{
140+
fputs("Usage: pdfmerge [OPTIONS] INPUT.pdf [... INPUT.pdf] >OUTPUT.pdf\n", out);
141+
fputs("Options:\n", out);
142+
fputs(" --help Show help.\n", out);
143+
fputs(" -o OUTPUT.pdf Send output to filename instead of stdout.\n", out);
144+
145+
return (out == stdout ? 0 : 1);
146+
}

0 commit comments

Comments
 (0)