概要
- Java 標準ライブラリの Graphics2D クラスと外部ライブラリを使用して、ベクターグラフィックス画像 (PDF,SVG,PPT,EPS,SWF) を出力する
- 具体的な描画処理は Graphics2D を使用して共通化する
- 各種ベクター形式画像フォーマットへの出力は外部ライブラリを使用する
- 今回のプログラムは Graphics2D を使って描画しているような振る舞いをするが、実際には各種フォーマットに対応した Graphics2D のサブクラスが処理をしている
- 確認用に PNG (Portable Network Graphics) 画像も出力する
使用ライブラリ
- PDF (Portable Document Format): Orson PDF
- SVG (Scalable Vector Graphics): Apache Batik
- PPT (PowerPoint): Apache POI
- EPS (Encapsulated PostScript): VectorGraphics2D
- SWF (Small Web Format / Shockwave Flash): FreeHEP VectorGraphics
今回の動作環境
- macOS Mojave
- OpenJDK 11.0.2
- Apache Maven 3.6.1
ソースコード
ソースコード一覧
- pom.xml: Maven のビルド用設定ファイル
- App.java: 各種フォーマットへ出力するプログラム
├── pom.xml
└── src
└── main
└── java
└── com
└── example
└── App.java
pom.xml: Maven のビルド用設定ファイル
- 各種外部ライブラリを dependencies に追加している
- 依存ライブラリを含めた実行可能な JAR ファイルを生成するため Maven Assembly Plugin を導入している
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- For PDF -->
<!-- https://mvnrepository.com/artifact/com.orsonpdf/orsonpdf -->
<dependency>
<groupId>com.orsonpdf</groupId>
<artifactId>orsonpdf</artifactId>
<version>1.9</version>
</dependency>
<!-- For SVG -->
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/batik-all -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<version>1.11</version>
<type>pom</type>
</dependency>
<!-- For PPT -->
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.0</version>
</dependency>
<!-- For EPS -->
<!-- https://mvnrepository.com/artifact/de.erichseifert.vectorgraphics2d/VectorGraphics2D -->
<dependency>
<groupId>de.erichseifert.vectorgraphics2d</groupId>
<artifactId>VectorGraphics2D</artifactId>
<version>0.13</version>
</dependency>
<!-- For SWF -->
<!-- https://mvnrepository.com/artifact/org.freehep/freehep-graphicsio-swf -->
<dependency>
<groupId>org.freehep</groupId>
<artifactId>freehep-graphicsio-swf</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- http://maven.apache.org/plugins/maven-assembly-plugin/ -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.example.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
App.java: 各種フォーマットへ出力するプログラム
package com.example;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import javax.imageio.ImageIO;
import org.w3c.dom.DOMImplementation;
// PDF
import com.orsonpdf.Page;
import com.orsonpdf.PDFDocument;
import com.orsonpdf.PDFGraphics2D;
// SVG
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
// PPT
import org.apache.poi.hslf.model.PPGraphics2D;
import org.apache.poi.hslf.usermodel.HSLFGroupShape;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
// EPS
import de.erichseifert.vectorgraphics2d.Document;
import de.erichseifert.vectorgraphics2d.Processor;
import de.erichseifert.vectorgraphics2d.Processors;
import de.erichseifert.vectorgraphics2d.VectorGraphics2D;
import de.erichseifert.vectorgraphics2d.intermediate.CommandSequence;
import de.erichseifert.vectorgraphics2d.util.PageSize;
// SWF
import org.freehep.graphicsio.swf.SWFGraphics2D;
public class App {
public static void main(String[] args) throws Exception {
createPNG();
createPDF();
createSVG();
createPPT();
createEPS();
createSWF();
}
/**
* 描画します。
*
* @param g Graphics2D オブジェクト
* @param w 描画範囲の横幅
* @param h 描画範囲の縦幅
*/
private static void draw(Graphics2D g, double w, double h) {
// 線の太さ
g.setStroke(new BasicStroke((float) (w + h) / 20.0f));
// 背景
g.setPaint(Color.LIGHT_GRAY);
g.fill(new Rectangle2D.Double(0, 0, w, h));
// 枠線
g.setPaint(Color.BLUE);
g.draw(new Rectangle2D.Double(0, 0, w, h));
// 円
g.setPaint(Color.RED);
g.fill(new Ellipse2D.Double(w / 4, h / 4, w / 2, h / 2));
// 線
g.setPaint(new Color(255, 255, 0, 100));
Line2D line = new Line2D.Double(w / 8, h / 8, w / 2, h / 2);
g.draw(line);
}
/**
* PNG (Portable Network Graphics) ファイルを出力します。
*/
private static void createPNG() throws IOException {
int w = 297 * 2;
int h = 210 * 2;
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
draw(g, w, h);
ImageIO.write(image, "png", new File("png.png"));
}
/**
* PDF (Portable Document Format) ファイルを出力します。
*/
private static void createPDF() throws Exception {
// 1 inch = 25.4mm = 72pt
double w = 297 * 72 / 25.4;
double h = 210 * 72 / 25.4;
PDFDocument pdfDoc = new PDFDocument();
Page page = pdfDoc.createPage(new Rectangle2D.Double(0, 0, w, h));
PDFGraphics2D g = page.getGraphics2D();
draw(g, w, h);
pdfDoc.writeToFile(new File("pdf.pdf"));
}
/**
* SVG (Scalable Vector Graphics) ファイルを出力します。
*/
private static void createSVG() throws IOException {
int w = 297 * 2;
int h = 210 * 2;
DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation();
String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
org.w3c.dom.Document doc = domImpl.createDocument(svgNS, "svg", null);
SVGGraphics2D g = new SVGGraphics2D(doc);
g.setSVGCanvasSize(new Dimension(w, h));
draw(g, w, h);
g.stream("svg.svg");
}
/**
* PPT (PowerPoint) ファイルを出力します。
*/
private static void createPPT() throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow();
Dimension pageSize = ppt.getPageSize();
double w = 297;
double h = 210;
double coef = Math.min(pageSize.getWidth() / w, pageSize.getHeight() / h);
w = w * coef;
h = h * coef;
HSLFSlide slide = ppt.createSlide();
HSLFGroupShape group = slide.createGroup();
Rectangle2D bounds = group.getAnchor();
bounds.setRect(0, 0, w, h);
PPGraphics2D g = new PPGraphics2D(group);
draw(g, w, h);
try (FileOutputStream out = new FileOutputStream("ppt.ppt")) {
ppt.write(out);
}
}
/**
* EPS (Encapsulated PostScript) ファイルを出力します。
*/
private static void createEPS() throws IOException {
int w = 297 * 2;
int h = 210 * 2;
VectorGraphics2D g = new VectorGraphics2D();
draw(g, w, h);
CommandSequence commands = g.getCommands();
Processor processor = Processors.get("eps");
PageSize size = new PageSize(w, h);
Document doc = processor.getDocument(commands, size);
doc.writeTo(new FileOutputStream("eps.eps"));
}
/**
* SWF (Small Web Format / Shockwave Flash) ファイルを出力します。
*/
private static void createSWF() throws IOException {
int w = 297 * 2;
int h = 210 * 2;
SWFGraphics2D g = new SWFGraphics2D(new File("swf.swf"), new Dimension(w, h));
g.writeHeader();
g.startExport();
draw(g, w, h);
g.endExport();
g.dispose();
}
}
プログラムをビルドして実行
Maven で実行可能な JAR ファイルを生成する。
$ mvn package
java コマンドで JAR ファイルを指定して実行する。
$ java -jar target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar
これで PNG, PDF, SVG, PPT, EPS, SWF の6種類のファイルが出力できる。
出力された各種ベクターグラフィックス画像ファイル
PNG (Portable Network Graphics)
PNG はベクター形式の画像フォーマットではないが比較用に載せておく。
PNG ファイルの情報をコマンドで確認する。
$ file png.png
png.png: PNG image data, 594 x 420, 8-bit/color RGBA, non-interlaced
$ pngcheck png.png
OK: png.png (594x420, 32-bit RGB+alpha, non-interlaced, 99.3%).
画像は macOS Mojave のプレビューアプリで閲覧したもの。
PDF (Portable Document Format)
PDF ファイルの情報をコマンドで確認する。
$ file pdf.pdf
pdf.pdf: PDF document, version 1.4
$ pdfinfo pdf.pdf
Producer: OrsonPDF 1.7
CreationDate: Sun Jul 28 15:24:27 2019
ModDate: Sun Jul 28 15:24:27 2019
Tagged: no
Form: none
Pages: 1
Encrypted: no
Page size: 841.89 x 595.276 pts (A4) (rotated 0 degrees)
File size: 1138 bytes
Optimized: no
PDF version: 1.4
画像は Adobe Acrobat Reader DC で閲覧したもの。
SVG (Scalable Vector Graphics)
SVG ファイルの情報をコマンドで確認する。
$ file svg.svg
svg.svg: SVG Scalable Vector Graphics image
$ identify svg.svg
svg.svg SVG 594x420 594x420+0+0 16-bit sRGB 1379B 0.000u 0:00.012
画像は Inkscape で閲覧したもの。ベクターデータのオブジェクトが確認できる。
SVG は XML 文書なので中身がテキストデータになっており確認しやすい。生成された SVG ファイルの中身をここに載せておく。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg stroke-dasharray="none" shape-rendering="auto" xmlns="http://www.w3.org/2000/svg" font-family="'Dialog'" width="594" text-rendering="auto" fill-opacity="1" contentScriptType="text/ecmascript" color-interpolation="auto" color-rendering="auto" preserveAspectRatio="xMidYMid meet" font-size="12px" fill="black" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="black" image-rendering="auto" stroke-miterlimit="10" zoomAndPan="magnify" version="1.0" stroke-linecap="square" stroke-linejoin="miter" contentStyleType="text/css" font-style="normal" height="420" stroke-width="1" stroke-dashoffset="0" font-weight="normal" stroke-opacity="1"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><g fill="silver" stroke-width="50.7" stroke="silver"
><rect x="0" width="594" height="420" y="0" stroke="none"
/><rect fill="none" x="0" width="594" height="420" y="0" stroke="blue"
/><ellipse rx="148.5" fill="red" ry="105" cx="297" cy="210" stroke="none"
/></g
><g fill="rgb(255,255,0)" fill-opacity="0.3922" stroke-width="50.7" stroke-opacity="0.3922" stroke="rgb(255,255,0)"
><line y2="210" fill="none" x1="74.25" x2="297" y1="52.5"
/></g
></g
></svg
>
PPT (PowerPoint)
PPT ファイルの情報をコマンドで確認する。
$ file ppt.ppt
ppt.ppt: Composite Document File V2 Document, Little Endian, Os: Windows, Version 5.1, Code page: 1252, Title: PowerPoint Presentation, Revision Number: 0, Name of Creating Application: Microsoft PowerPoint, Last Saved Time/Date: Mon Apr 7 20:47:14 2003, Number of Words: 0
画像は Keynote で閲覧したもの。ベクターデータのオブジェクトが確認できる。
EPS (Encapsulated PostScript)
EPS ファイルの情報をコマンドで確認する。
$ file eps.eps
eps.eps: PostScript document text conforming DSC level 3.0, type EPS, Level 3
画像は macOS Mojave のプレビューアプリで閲覧したもの。ベクターデータのオブジェクトが確認できる。
SWF (Small Web Format / Shockwave Flash)
SWF ファイルの情報をコマンドで確認する。
$ file swf.swf
swf.swf: Macromedia Flash data (compressed), version 8
画像は Elmedia Video Player で閲覧したもの。
参考資料
OrsonPDF
- Orson PDF
- GitHub - jfree/orsonpdf: A fast, lightweight PDF generator for the Java platform
- Overview (OrsonPDF version 1.7)
Apache Batik
- Apache(tm) Batik SVG Toolkit - a Java-based toolkit for applications or applets that want to use images in the Scalable Vector Graphics (SVG)
- SVG Generator: SVGGraphics2D
- Overview (Apache Batik Javadoc)
Apache POI
- POI-HSLF and and POI-XLSF - Java API To Access Microsoft Powerpoint Format Files
- Busy Developers' Guide to HSLF drawing layer
- Overview (POI API Documentation)
VectorGraphics2D
- VectorGraphics2D
- GitHub - eseifert/vectorgraphics2d: Graphics2D implementations to export various vector file formats
- vectorgraphics2d/VectorGraphics2D.java at master · eseifert/vectorgraphics2d · GitHub