>
 

Rendering slideshows, WMF, EMF and EMF+

Note
Please be aware, that the documentation on this page reflects the current development, which might not have been released. If you rely on a unreleased feature, either use a nightly development build or feel free to ask on the mailing list for the release schedule.

Rendering slideshows, WMF, EMF and EMF+

For rendering slideshow (HSLF/XSLF), WMF, EMF and EMF+ pictures, POI provides an utility class :

Usage: PPTX2PNG [options] <.ppt/.pptx/.emf/.wmf file or 'stdin'>
Options:
-scale <float> scale factor
-fixSide <side> specify side (long,short,width,height) to fix - use <scale> as amount of pixels
-slide <integer> 1-based index of a slide to render
-format <type> png,gif,jpg,svg,pdf (log,null for testing)
-outdir <dir> output directory, defaults to origin of the ppt/pptx file
-outfile <file> output filename, defaults to "${basename}-${slideno}.${format}"
-outpat <pattern> output filename pattern, defaults to "${basename}-${slideno}.${format}"
patterns: basename, slideno, format, ext
-dump <file> dump the annotated records to a file
-quiet do not write to console (for normal processing)
-ignoreParse ignore parsing error and continue with the records read until the error
-extractEmbedded extract embedded parts
-inputType <type> default input file type (OLE2,WMF,EMF), default is OLE2 = Powerpoint
some files (usually wmf) don't have a header, i.e. an identifiable file magic
-textAsShapes text elements are saved as shapes in SVG, necessary for variable spacing
often found in math formulas
-charset <cs> sets the default charset to be used, defaults to Windows-1252
-emfHeaderBounds force the usage of the emf header bounds to calculate the bounding box
-fontdir <dir> (PDF only) font directories separated by ";" - use $HOME for current users home dir
defaults to the usual plattform directories
-fontTtf <regex> (PDF only) regex to match the .ttf filenames
-fontMap <map> ";"-separated list of font mappings <typeface from>:<typeface to>

Instructions to run

Download the and for SVG/PDF the additional dependencies.

Execute the java command (Unix-paths needs to be replaced for Windows - use "-charset" for non-western WMF/EMFs):

java -cp poi-5.0.0-SNAPSHOT.jar:poi-ooxml-5.0.0-SNAPSHOT.jar:poi-ooxml-schemas-5.0.0-SNAPSHOT.jar:poi-scratchpad-5.0.0-SNAPSHOT.jar:lib/*:ooxml-lib/*:auxiliary/* org.apache.poi.xslf.util.PPTX2PNG -format png -fixside long -scale 1000 -charset GBK file.pptx
Note
JDK 1.8 is by default using the PiscesRenderingEngine and affected by . To workaround thise, use the MarlinRenderingEngine which is experimental provided starting from via -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine or for older jdk builds, .

Integrate rendering in your code

#1 - Use PPTX2PNG via file or stdin

For file system access, you need to save your slideshow/WMF/EMF/EMF+ first to disc and then call PPTX2PNG.main() with the corresponding parameters.

for stdin access, you need to redirect System.in before:

/* the file content */
InputStream is = ...;
/* Save and set System.in */
InputStream oldIn = System.in;
try {
System.setIn(is);
String[] args = {
"-format", "png", // png,gif,jpg,svg or null for test
"-outdir", new File("out/").getCanonicalPath(),
"-outfile", "export.png",
"-fixside", "long",
"-scale", "800",
"-ignoreParse",
"stdin"
};
PPTX2PNG.main(args);
} finally {
System.setIn(oldIn);
}

#2 - Render WMF / EMF / EMF+ via the *Picture classes

File f = samples.getFile("santa.wmf");
try (FileInputStream fis = new FileInputStream(f)) {
// for WMF
HwmfPicture wmf = new HwmfPicture(fis);
// for EMF / EMF+
HemfPicture emf = new HemfPicture(fis);
Dimension dim = wmf.getSize();
int width = Units.pointsToPixel(dim.getWidth());
// keep aspect ratio for height
int height = Units.pointsToPixel(dim.getHeight());
double max = Math.max(width, height);
if (max > 1500) {
width *= 1500/max;
height *= 1500/max;
}
BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bufImg.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
wmf.draw(g, new Rectangle2D.Double(0,0,width,height));
g.dispose();
ImageIO.write(bufImg, "PNG", new File("bla.png"));
}

#3 - Render slideshows directly

File file = new File("example.pptx");
double scale = 1.5;
try (SlideShow<?, ?> ss = SlideShowFactory.create(file, null, true)) {
Dimension pgsize = ss.getPageSize();
int width = (int) (pgsize.width * scale);
int height = (int) (pgsize.height * scale);
for (Slide<?, ?> slide : ss.getSlides()) {
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = img.createGraphics();
// default rendering options
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setRenderingHint(Drawable.BUFFERED_IMAGE, new WeakReference<>(img));
graphics.scale(scale, scale);
// draw stuff
slide.draw(graphics);
ImageIO.write(img, "PNG", new File("output.png"));
graphics.dispose();
img.flush();
}
}