本文介绍了使用java将ppt文件转换为图片的方法,支持.ppt和.pptx两种格式。通过apache poi库处理ppt文件内容,利用batik rasterizer生成高质量图片。
核心实现包括:
- 1)设置字体映射和渲染参数;
- 2)按幻灯片页数循环转换;
- 3)自动裁剪图片空白边缘。
代码提供了对两种ppt格式的处理类(ppttoimageutils)和图片处理工具类(imageutils),建议使用jdk11及以上版本和poi5.2.3版本以确保兼容性。该方法可批量转换ppt为png图片,适用于文档自动化处理场景
1. maven引入
<!-- for .pptx files (office 2007+) -->
<dependency>
<groupid>org.apache.poi</groupid>
<artifactid>poi-ooxml</artifactid>
<version>5.2.3</version>
</dependency>
<!-- for .ppt files (office 97-2003) -->
<dependency>
<groupid>org.apache.poi</groupid>
<artifactid>poi-scratchpad</artifactid>
<version>5.2.3</version>
</dependency>
<dependency>
<groupid>org.apache.xmlgraphics</groupid>
<artifactid>batik-rasterizer</artifactid>
<version>1.14</version>
</dependency>2. 代码
2.1 ppttoimageutils
import cn.iocoder.yudao.module.agent.util.ppt.imageutils;
import lombok.extern.slf4j.slf4j;
import org.apache.commons.lang3.stringutils;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.openxml4j.util.zipsecurefile;
import org.apache.poi.xslf.usermodel.*;
import org.springframework.stereotype.component;
import javax.imageio.imageio;
import java.awt.*;
import java.awt.geom.rectangle2d;
import java.awt.image.bufferedimage;
import java.io.file;
import java.io.fileinputstream;
import java.io.ioexception;
import java.nio.file.files;
import java.nio.file.paths;
import java.util.list;
import java.util.*;
import java.util.stream.collectors;
@slf4j
@component
public class ppttoimageutils {
private static final map<string, font> font_map = new hashmap<>();
private static final string default_font = "宋体";
static {
graphicsenvironment environment = graphicsenvironment.getlocalgraphicsenvironment();
for (font font : environment.getallfonts()) {
addfont(font);
}
log.info("supporting fonts: \n{}", stringutils.join(font_map.keyset(), '\n'));
// 降低压缩比阈值,防止误判正常 emf 文件
zipsecurefile.setmininflateratio(0.001);
// 设置最大条目大小(100mb)
zipsecurefile.setmaxentrysize(100 * 1024 * 1024);
}
@suppresswarnings("weakeraccess")
public static void addfont(font font) {
font_map.put(font.getfamily(), font);
}
/**
* 将ppt文件转换为多张图像
*
* @param pptfile ppt文件路径
* @param outputdir 输出目录
* @return 生成的图像文件路径列表
*/
public static list<string> convertppttoimages(string pptfile, string outputdir) throws ioexception {
if (pptfile.endswith("pptx")) {
return dopptxtoimages(pptfile, outputdir);
} else if (pptfile.endswith("ppt")) {
return doppttoimages(pptfile, outputdir);
} else
return new arraylist<>();
}
/**
* 将ppt文件转换为多张图像
*
* @param pptfile ppt文件路径
* @param outputdir 输出目录
* @return 生成的图像文件路径列表
*/
public static list<string> dopptxtoimages(string pptfile, string outputdir) throws ioexception {
list<string> imagepaths = new arraylist<>();
try (fileinputstream is = new fileinputstream(pptfile);
xmlslideshow ppt = new xmlslideshow(is)) {
// 创建输出目录
files.createdirectories(paths.get(outputdir));
// 获取ppt尺寸
dimension pagesize = ppt.getpagesize();
// 计算带边距的尺寸
int width = (int) pagesize.getwidth();
int height = (int) pagesize.getheight();
// 设置缩放比例以提高图像质量
double scale = 2;
int scaledwidth = (int) (width * scale);
int scaledheight = (int) (width * scale);
list<xslfslide> slides = ppt.getslides();
log.info(">>>>ppt转图片:{}页开始>>>>", slides.size());
int index = 1;
for (int i = 0; i < slides.size(); i++) {
final int slidenum = index;
system.out.println("converting slide " + slidenum + "...");
log.info(">>>>ppt转图片第{}页>>>>", i + 1);
xslfslide slide = slides.get(i);
fixfont(slide);
// 创建缓冲图像
log.info(">>>>ppt转图片第{}页,{}>>>>", i + 1, "创建缓冲图像开始");
bufferedimage img = new bufferedimage(scaledwidth, scaledheight, bufferedimage.type_int_rgb);
graphics2d graphics = img.creategraphics();
// 设置渲染提示以提高质量
log.info(">>>>ppt转图片第{}页,{}>>>>", i + 1, "设置渲染提示以提高质量开始");
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);
// 设置背景为白色
log.info(">>>>ppt转图片第{}页,{}>>>>", i + 1, "设置背景为白色开始");
// color transparentcolor = new color(255, 0, 0, 0);
// graphics.setpaint(transparentcolor);
graphics.setcolor(color.white);
graphics.setpaint(color.white);
// 禁用所有透明相关功能
graphics.setcomposite(alphacomposite.srcover);
graphics.setbackground(color.white);
graphics.fill(new rectangle2d.float(0, 0, scaledwidth, scaledheight));
// 缩放图形上下文
log.info(">>>>ppt转图片第{}页,{}>>>>", i + 1, "缩放图形上下文开始");
graphics.scale(scale, scale);
// 绘制幻灯片
log.info(">>>>ppt转图片第{}页,{}>>>>", i + 1, "绘制幻灯片开始");
slide.draw(graphics);
// 保存图像
log.info(">>>>ppt转图片第{}页,{}>>>>", i + 1, "保存图像开始");
string outputpath = string.format("%s/slide_%03d.png", outputdir, i + 1);
imageio.write(img, "png", new file(outputpath));
log.info(">>>>ppt转图片第{}页:{}>>>>", i + 1, outputpath);
imagepaths.add(outputpath);
graphics.dispose();
//切掉白色空白区域
imageutils.imagewhitespace(outputpath);
}
index++;
} catch (exception e) {
e.printstacktrace();
log.error(e.getmessage(), e);
}
return imagepaths;
}
/**
* 将ppt文件转换为多张图像
*
* @param pptfile ppt文件路径
* @param outputdir 输出目录
* @return 生成的图像文件路径列表
*/
public static list<string> doppttoimages(string pptfile, string outputdir) throws ioexception {
list<string> imagepaths = new arraylist<>();
try (fileinputstream is = new fileinputstream(pptfile);
hslfslideshow ppt = new hslfslideshow(is)) {
// 创建输出目录
files.createdirectories(paths.get(outputdir));
// 获取ppt尺寸
dimension pagesize = ppt.getpagesize();
// 计算带边距的尺寸
// double marginwidth = pagesize.width * 20 / 100;
// double marginheight = pagesize.height * 20 / 100;
int width = (int) pagesize.getwidth();
int height = (int) pagesize.getheight();
// 设置缩放比例以提高图像质量
double scale = 2.0;
int scaledwidth = (int) (width * scale);
int scaledheight = (int) (width * scale);
list<hslfslide> slides = ppt.getslides();
for (int i = 0; i < slides.size(); i++) {
hslfslide slide = slides.get(i);
// system.out.println("页码: " + (i+1));
fixhfont(slide);
// 创建缓冲图像
bufferedimage img = new bufferedimage(scaledwidth, scaledheight, bufferedimage.type_byte_gray);
graphics2d graphics = img.creategraphics();
// 设置渲染提示以提高质量
// 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.setpaint(color.white);
graphics.fill(new rectangle2d.float(0, 0, scaledwidth, scaledheight));
// 缩放图形上下文
graphics.scale(scale, scale);
// 绘制幻灯片
slide.draw(graphics);
// 保存图像
string outputpath = string.format("%s/slide_%03d.png", outputdir, i + 1);
imageio.write(img, "png", new file(outputpath));
imagepaths.add(outputpath);
graphics.dispose();
//切掉白色空白区域
imageutils.imagewhitespace(outputpath);
}
} catch (exception e) {
e.printstacktrace();
}
return imagepaths;
}
private static void fixfont(xslfslide slide) {
for (xslfshape shape : slide.getshapes()) {
if (shape instanceof xslftextshape) {
for (xslftextparagraph p : ((xslftextshape) shape).gettextparagraphs()) {
for (xslftextrun r : p.gettextruns()) {
r.setfontfamily(default_font); // 或“wenquanyi zen hei”
// if (r.getfontcolor()==null)
r.setfontcolor(color.black);
}
}
}
}
}
private static void fixhfont(hslfslide slide) {
for (hslfshape shape : slide.getshapes()) {
if (shape instanceof hslftextshape) {
for (hslftextparagraph p : ((hslftextshape) shape).gettextparagraphs()) {
for (hslftextrun r : p.gettextruns()) {
r.setfontfamily(default_font); // 或“wenquanyi zen hei”
// if (r.getfontcolor()==null)
r.setfontcolor(color.black);
}
}
} else if (shape instanceof hslftable) {
hslftable shape1 = (hslftable) shape;
int r = shape1.getnumberofrows();
int c = shape1.getnumberofcolumns();
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
hslftablecell cell = shape1.getcell(i, j);
for (hslftextparagraph p : cell) {
for (hslftextrun text : p.gettextruns()) {
text.setfontfamily(default_font); // 或“wenquanyi zen hei”
// if (r.getfontcolor()==null)
text.setfontcolor(color.black);
}
}
}
}
}
}
}
public static void main(string[] args) throws ioexception {
string pptfile = "e:/文档/项目.pptx";
string outputdir = "e:/文档/temp";
list<string> imagepaths = convertppttoimages(pptfile, outputdir);
}
}
2.2 imageutils
import javax.imageio.imageio;
import java.awt.image.bufferedimage;
import java.io.file;
public class imageutils {
public static boolean imagewhitespace(string filepath) {
try {
// 读取原始图像
bufferedimage originalimage = imageio.read(new file(filepath));
int width = originalimage.getwidth();
int height = originalimage.getheight();
// 从底部向上扫描,检测白色区域
int whitethreshold = 0xffffff - 10; // 接近白色的阈值(允许微小差异)
int bottomblankheight = 0;
boolean isblank = true;
for (int y = height - 1; y >= 0 && isblank; y--) {
for (int x = 0; x < width; x++) {
int pixel = originalimage.getrgb(x, y) & 0xffffff;
if (pixel < whitethreshold) {
isblank = false;
break;
}
}
if (isblank) {
bottomblankheight++;
}
}
// 计算需要裁剪的空白高度(去掉90%)
int cropheight = (int) (bottomblankheight * 0.9);
int newheight = height - cropheight ;
// 裁剪图像(保留上方部分)
bufferedimage croppedimage = originalimage.getsubimage(0, 0, width, newheight < 1080 ? 1080 : newheight);
// 保存结果
imageio.write(croppedimage, "png", new file(filepath));
// system.out.println("下方空白区域已裁剪约90%,保存为 slide_010_cropped.png");
} catch (exception e) {
e.printstacktrace();
return false;
}
return true;
}
public static void main(string[] args) {
string filepath = "e:/文档/temp/slide_005.png";
imagewhitespace(filepath);
}
}2.3 效果

3. 总结
jdk 版本建议为11及以上,poi版本建议为5.2.3,其他版本有可能会造成文字缺失。
到此这篇关于java实现将ppt(.ppt和.pptx)转为图片的文章就介绍到这了,更多相关java ppt转图片内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论