PPT生成PNG---解决中文乱码和字体大小、位置偏移等问题

POI版本:3.15

代码如下:改编自poi源码中的工具类,源码中的出现乱码问题。网上搜的版本生成的图片字体大小和偏移有问题。

package POI;

/*
 *  ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one or more
 *    contributor license agreements.  See the NOTICE file distributed with
 *    this work for additional information regarding copyright ownership.
 *    The ASF licenses this file to You under the Apache License, Version 2.0
 *    (the "License"); you may not use this file except in compliance with
 *    the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 * ====================================================================
 */

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;

import javax.imageio.ImageIO;

import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.apache.poi.xslf.usermodel.XSLFTextShape;

public class PPT2PNG1 {

	static void usage(String error) {
		String msg = "Usage: PPTX2PNG [options] <ppt or pptx file>\n"
				+ (error == null ? "" : ("Error: " + error + "\n")) + "Options:\n"
				+ "    -scale <float>   scale factor\n" + "    -slide <integer> 1-based index of a slide to render\n"
				+ "    -format <type>   png,gif,jpg (,null for testing)"
				+ "    -outdir <dir>    output directory, defaults to origin of the ppt/pptx file"
				+ "    -quiet           do not write to console (for normal processing)";

		System.out.println(msg);
		// no System.exit here, as we also run in junit tests!
	}

	public static void main(String[] args) throws Exception {
		if (args.length == 0) {
			usage(null);
			return;
		}

		String slidenumStr = "-1";
		float scale = 1;
		File file = null;
		String format = "png";
		File outdir = null;
		boolean quiet = false;

		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith("-")) {
				if ("-scale".equals(args[i])) {
					scale = Float.parseFloat(args[++i]);
				} else if ("-slide".equals(args[i])) {
					slidenumStr = args[++i];
				} else if ("-format".equals(args[i])) {
					format = args[++i];
				} else if ("-outdir".equals(args[i])) {
					System.err.println(args[++i]);
					outdir = new File(args[++i]);
				} else if ("-quiet".equals(args[i])) {
					quiet = true;
				}
			} else {
				file = new File(args[i]);
			}
		}

		if (format == null || !format.matches("^(png|gif|jpg|null)$")) {
			usage("Invalid format given");
			return;
		}

		if (outdir == null) {
			outdir = file.getParentFile();
		}

		if (!"null".equals(format) && (outdir == null || !outdir.exists() || !outdir.isDirectory())) {
			usage("Output directory doesn't exist");
			return;
		}

		if (scale < 0) {
			usage("Invalid scale given");
			return;
		}

		if (!quiet) {
			System.out.println("Processing " + file);
		}
		FileInputStream is =new FileInputStream(file);
		XMLSlideShow ppt = new XMLSlideShow(is);
		try {
			List<XSLFSlide> slides = ppt.getSlides();
			Set<Integer> slidenum = slideIndexes(slides.size(), slidenumStr);

			if (slidenum.isEmpty()) {
				usage("slidenum must be either -1 (for all) or within range: [1.." + slides.size() + "] for " + file);
				return;
			}

			Dimension pgsize = ppt.getPageSize();
			int width = (int) (pgsize.width * scale);
			int height = (int) (pgsize.height * scale);

			for (Integer slideNo : slidenum) {
				XSLFSlide slide = slides.get(slideNo);
				for (XSLFShape shape : ppt.getSlides().get(slideNo).getShapes()) {
					if (shape instanceof XSLFTextShape) {
						XSLFTextShape tsh = (XSLFTextShape) shape;
						for (XSLFTextParagraph p : tsh) {
							for (XSLFTextRun r : p) {
								r.setFontFamily("宋体");
							}
						}
					}
				}
				String title = slide.getTitle();
				if (!quiet) {
					System.out.println("Rendering slide " + slideNo + (title == null ? "" : ": " + title));
				}

				BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
				Graphics2D graphics = img.createGraphics();
				DrawFactory.getInstance(graphics).fixFonts(graphics);

				// 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.scale(scale, scale);
				// draw stuff
				slide.draw(graphics);

				// save the result
				if (!"null".equals(format)) {
					String outname = file.getName().replaceFirst(".pptx?", "");
					outname = String.format(Locale.ROOT, "%1$s-%2$04d.%3$s", outname, slideNo, format);
					File outfile = new File(outdir, outname);
					ImageIO.write(img, format, outfile);
				}

				graphics.dispose();
				img.flush();
			}
		} finally {
			ppt.close();
			is.close();
		}

		if (!quiet) {
			System.out.println("Done");
		}
	}

	private static Set<Integer> slideIndexes(final int slideCount, String range) {
		Set<Integer> slideIdx = new TreeSet<Integer>();
		if ("-1".equals(range)) {
			for (int i = 0; i < slideCount; i++) {
				slideIdx.add(i);
			}
		} else {
			for (String subrange : range.split(",")) {
				String idx[] = subrange.split("-");
				switch (idx.length) {
				default:
				case 0:
					break;
				case 1: {
					int subidx = Integer.parseInt(idx[0]);
					if (subrange.contains("-")) {
						int startIdx = subrange.startsWith("-") ? 0 : subidx;
						int endIdx = subrange.endsWith("-") ? slideCount : Math.min(subidx, slideCount);
						for (int i = Math.max(startIdx, 1); i < endIdx; i++) {
							slideIdx.add(i - 1);
						}
					} else {
						slideIdx.add(Math.max(subidx, 1) - 1);
					}
					break;
				}
				case 2: {
					int startIdx = Math.min(Integer.parseInt(idx[0]), slideCount);
					int endIdx = Math.min(Integer.parseInt(idx[1]), slideCount);
					for (int i = Math.max(startIdx, 1); i < endIdx; i++) {
						slideIdx.add(i - 1);
					}
					break;
				}
				}
			}
		}
		return slideIdx;
	}
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值