PDF/A、PDF/X 標準ドキュメントのクローン。スタンプ、XMP メタデータの追加、ページコンテンツの追加などの拡張処理のための簡単な使用方法を示します。次の挙げる入力文書の内容によりクローンを作ります。
/*
* Clone PDF/A, PDF/UA and PDF/X standard documents
* This is useful as basis for additional processing,
* such as stamping, adding XMP metadata, adding page content, etc.
*
* The following aspects of the input document are cloned:
* - PDF/A, PDF/UA and PDF/X version
* - PDF/A or PDF/X output intent (if present)
* - document language (if present)
* - all pages including page geometry, i.e. page boxes and Rotate key
* - the structure elements (tags); if required, an additional
* tag is inserted on top of the imported page elements
* - XMP document metadata
* This will generally also clone document info fields since these are
* synchronized with XMP in the majority of modern PDF documents.
*
* To demonstrate coordinate transformations which may be required
* to add new page content this topic adds a stamp across all pages.
*
* Input documents may conform to any combination of PDF/A, PDF/UA
* and PDF/X simultaneously.
*
* Note: Except for the names of the input and output documents the three
* Cookbook topics clone_pdfa, clone_pdfua and clone_pdfx are exact copies.
* They are included multiply so that they can easily be found in the
* PDF/A, PDF/UA and PDF/X categories.
*
* required software: PDFlib+PDI/PPS 10
* required data: PDF/A, PDF/UA or PDF/X input document
*/
package com.pdflib.cookbook.pdflib.pdfa;
import com.pdflib.pdflib;
import com.pdflib.PDFlibException;
public class clone_pdfa {
public static void main(String argv[]) {
/* This is where the data files are. Adjust as necessary. */
String searchpath = "../input";
/* By default annotations are also imported. In some cases this
* requires the Noto fonts for creating annotation appearance streams.
* We therefore set the searchpath to also point to the font directory.
*/
String fontpath = "../resource/font";
pdflib p = null;
String pdfinputfile = "PLOP-datasheet-PDFA-1b.pdf";
String title = "clone_pdfa";
String pdfaversion, pdfuaversion, pdfxversion, inputlang;
boolean taggedinput;
String optlist = "";
byte xmp[];
/* The following standard flavors can be cloned: */
String supportedflavors[] = {
"PDF/A-1a:2005", "PDF/A-1b:2005",
"PDF/A-2a", "PDF/A-2b", "PDF/A-2u",
"PDF/A-3a", "PDF/A-3b", "PDF/A-3u",
"PDF/X-3:2003",
"PDF/X-4", "PDF/X-4p",
"PDF/X-5g", "PDF/X-5pg", "PDF/X-5n",
"PDF/UA-1",
"none",
};
int indoc, endpage, pageno, i;
double x, y, phi, width, height;
int exitcode = 0;
try {
p = new pdflib();
p.set_option("searchpath={" + searchpath + "}");
p.set_option("searchpath={" + fontpath + "}");
/* This means we must check return values of load_font() etc. */
p.set_option("errorpolicy=return");
/*
* Open the input PDF, preserve tags if present (for cloning
* PDF/A-1/2/3a and PDF/UA)
*/
indoc = p.open_pdi_document(pdfinputfile, "usetags=true");
if (indoc == -1) {
throw new Exception("Error: " + p.get_apiname() + ": "
+ p.get_errmsg());
}
/*
* Read PDF/A, PDF/UA and PDF/X version of the input document
*/
pdfaversion = p.pcos_get_string(indoc, "pdfa");
pdfuaversion = p.pcos_get_string(indoc, "pdfua");
pdfxversion = p.pcos_get_string(indoc, "pdfx");
for (i = 0; i < supportedflavors.length; i++) {
if (pdfaversion.equals(supportedflavors[i])) {
optlist += " pdfa=" + pdfaversion;
break;
}
}
if (i == supportedflavors.length)
System.err.println("Error: Cannot clone " + pdfaversion
+ " documents");
for (i = 0; i < supportedflavors.length; i++) {
if (pdfuaversion.equals(supportedflavors[i])) {
optlist += " pdfua=" + pdfuaversion;
break;
}
}
if (i == supportedflavors.length)
System.err.println("Error: Cannot clone " + pdfuaversion
+ " documents");
for (i = 0; i < supportedflavors.length; i++) {
if (pdfxversion.equals(supportedflavors[i])) {
optlist += " pdfx=" + pdfxversion;
break;
}
}
if (i == supportedflavors.length)
System.err.println("Error: Cannot clone " + pdfxversion
+ " documents");
/*
* Read language entry of the input document if present
*/
if (p.pcos_get_string(indoc, "type:/Root/Lang").equals("string")) {
inputlang = p.pcos_get_string(indoc, "/Root/Lang");
optlist += " lang=" + inputlang;
}
else if (pdfuaversion.equals("PDF/UA-1"))
{
/* PDF/UA documents don't necessarily need the /Lang entry
* in the Catalog, but PDFlib requires the "lang" option.
* We supply a default language (which may be wrong) to
* ensure that such documents can be cloned nevertheless.
*/
final String DEFAULT_LANGUAGE = "en";
optlist += " lang=" + DEFAULT_LANGUAGE;
}
else
inputlang = "";
/*
* Clone XMP metadata of input document if present
*/
if (p.pcos_get_string(indoc, "type:/Root/Metadata")
.equals("stream")) {
xmp = p.pcos_get_stream(indoc, "", "/Root/Metadata");
p.create_pvf("/xmp/document.xmp", xmp, "");
optlist += " metadata={filename=/xmp/document.xmp}";
}
/*
* Read Tagged status of input document
*/
taggedinput = p.pcos_get_string(indoc, "tagged").equals("true");
if (taggedinput)
optlist += " tag={tagname=Document}";
/*
* Create a new document and clone PDF/A, PDF/UA and PDF/X status
*/
if (p.begin_document(title + ".pdf", optlist) == -1)
throw new Exception("Error: " + p.get_apiname() + ": "
+ p.get_errmsg());
p.set_info("Creator", "PDFlib Cookbook");
p.set_info("Title", title);
/*
* Clone PDF/A or PDF/X output intent
*/
if (p.process_pdi(indoc, -1, "action=copyoutputintent") == -1)
throw new Exception("Error: " + p.get_apiname() + ": "
+ p.get_errmsg());
/* Create a bookmark with the name of the input document */
p.create_bookmark(pdfinputfile, "");
endpage = (int) p.pcos_get_number(indoc, "length:pages");
/* Copy all pages of the input document */
for (pageno = 1; pageno <= endpage; pageno++) {
String lowerleftcorner[][] = {
{ "x1", "y1" }, /* 0 degrees */
{ "x2", "y2" }, /* 90 degrees */
{ "x3", "y3" }, /* 180 degrees */
{ "x4", "y4" }, /* 270 degrees */
};
int page = p.open_pdi_page(indoc, pageno, "cloneboxes");
if (page == -1) {
System.err.println("Error: " + p.get_errmsg());
continue;
}
/*
* Query the geometry of the cloned page. This is required to
* account for translated or rotated pages if we want to add
* more contents to the page.
*/
phi = p.info_pdi_page(page, "rotate", "");
/*
* Select the lower left corner depending on the rotation angle
*/
x = p.info_pdi_page(page, lowerleftcorner[(int) (phi / 90)][0],
"");
y = p.info_pdi_page(page, lowerleftcorner[(int) (phi / 90)][1],
"");
boolean fittingpossible = true;
String additionaltag = "";
if (taggedinput) {
int topleveltagcount = (int) p.info_pdi_page(page,
"topleveltagcount", "");
if (topleveltagcount == 0) {
/*
* The page doesn't contain any structure elements, i.e.
* it is empty or contains only Artifacts. Some
* applications may decide to skip such pages.
*
* We add an "Artifact" tag to work around an Acrobat
* bug.
*/
additionaltag = "tag={tagname=Artifact} ";
}
else if (p.info_pdi_page(page, "fittingpossible", "")
== 0) {
/*
* Try to place the page without any additional tag; if
* this doesn't work we insert another tag.
*/
additionaltag = "tag={tagname=P} ";
if (p.info_pdi_page(page, "fittingpossible",
additionaltag) == 0) {
fittingpossible = false;
}
}
}
if (fittingpossible) {
/* Page size will be adjusted by "cloneboxes" option */
p.begin_page_ext(0, 0, "width=a4.width height=a4.height");
optlist = "cloneboxes ";
if (taggedinput)
optlist += additionaltag;
p.fit_pdi_page(page, 0, 0, optlist);
/*
* Adjust the coordinate system to facilitate adding new
* page content on top of the cloned page.
*/
p.translate(x, y);
p.rotate(phi);
width = p.info_pdi_page(page, "pagewidth", "");
height = p.info_pdi_page(page, "pageheight", "");
/*
* Add some text on each page and tag it as Artifact.
*/
optlist = "fontname=NotoSerif-Regular "
+ "textrendering=1 stamp=ll2ur "
+ "boxsize={" + width + " " + height + "}";
if (taggedinput)
optlist += " tag={tagname=Artifact}";
p.fit_textline("Cloned page", 0, 0, optlist);
p.end_page_ext("");
}
else {
System.err.println("Skipping page " + pageno + " of '"
+ pdfinputfile + "': " + p.get_errmsg());
}
p.close_pdi_page(page);
}
p.end_document("");
p.delete_pvf("/xmp/document.xmp");
p.close_pdi_document(indoc);
}
catch (PDFlibException e) {
System.err.println("PDFlib exception occurred:");
System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
": " + e.get_errmsg());
exitcode = 1;
}
catch (Exception e) {
System.err.println(e);
exitcode = 1;
}
finally {
if (p != null) {
p.delete();
}
System.exit(exitcode);
}
}
}