PPTToImgConverter
This is a library that can convert slideshow (ppt or pptx format) into images (jpg, png, bmp or wbmp format) . It’s based on Apache POI,but with images of higher quality and simplier apis. What you need to use the library,is just importing the dependencies and the single class.
这个工具类可以将ppt或者pptx文件转换为图片(支持4中格式jpg、png、bmp和wbmp)。 它基于Apache poi,但转换图片质量更高,api更加简洁。 使用它,仅需导入依赖和唯一个一个类PPTToImgConverter
即可
Demo
Some examples to show how to use this. 这是一些展示如何使用的小例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<span class="pl-c">/**</span> <span class="pl-c"> *A simple demo, all slides will be converted, and the resolution of images is consistent with that of origin slideshow.</span> <span class="pl-c"> *简单例子,以自身分辨率输出ppt的每一页</span> <span class="pl-c"> */</span> <span class="pl-c">// set the parent directory of converted images, it's necessary. 设置图片输出目录。</span> <span class="pl-smi">PPTToImgConverter</span><span class="pl-k">.</span>dir(<span class="pl-s"><span class="pl-pds">"</span>E:/testppt<span class="pl-pds">"</span></span>) <span class="pl-c">//select a file or folder. 选择一个文件或者文件夹。</span> .file(<span class="pl-s"><span class="pl-pds">"</span>E:/test.pptx<span class="pl-pds">"</span></span>) <span class="pl-c">//start the conversion. 开始转换。</span> .convert(); <span class="pl-c">/**</span> <span class="pl-c"> *A demo with more configurations.</span> <span class="pl-c"> *一个稍微复杂点的例子。</span> <span class="pl-c"> */</span> <span class="pl-c">//set the parent directory of converted images. 设置图片输出目录。</span> <span class="pl-smi">PPTToImgConverter</span><span class="pl-k">.</span>dir(<span class="pl-s"><span class="pl-pds">"</span>E:/testppt<span class="pl-pds">"</span></span>) <span class="pl-c">//select multiple files or folders.设置多个文件或者文件夹。</span> .files(<span class="pl-k">new</span> <span class="pl-smi">String</span>[]{<span class="pl-s"><span class="pl-pds">"</span>E:/pptFolder<span class="pl-pds">"</span></span>,<span class="pl-s"><span class="pl-pds">"</span>E:/test.ppt<span class="pl-pds">"</span></span>}) <span class="pl-c">//set the start position. 设置起始页码。</span> .from(<span class="pl-c1">0</span>) <span class="pl-c">//set the end position, note that the end page will be converted,-1 means last page.</span> <span class="pl-c">//设置结束页码,-1表示倒数第一页,结束页码也会被转换。</span> .to(<span class="pl-k">-</span><span class="pl-c1">1</span>) <span class="pl-c">//set the width of resolution. 设置图片分辨率宽度。</span> .width(<span class="pl-c1">400</span>) <span class="pl-c">//set the height of resolution. 设置图片分辨率高度。</span> .height(<span class="pl-c1">300</span>) <span class="pl-c">//set the format of images. 设置图片格式</span> .imgFormat(<span class="pl-smi">PPTToImgConverter</span><span class="pl-c1"><span class="pl-k">.</span>PNG</span>) <span class="pl-c">//start the conversion. 开始转换。</span> .convert(); <span class="pl-c">/**</span> <span class="pl-c"> *other apis</span> <span class="pl-c"> *note the scale dose not influence the resolution of final images, and it's unnecessary to set.</span> <span class="pl-c"> *其他例子</span> <span class="pl-c"> */</span> <span class="pl-c">//set the parent directory of converted images. 设置图片输出目录。</span> <span class="pl-smi">PPTToImgConverter</span><span class="pl-k">.</span>dir(<span class="pl-s"><span class="pl-pds">"</span>E:/testppt<span class="pl-pds">"</span></span>) <span class="pl-c">//set the scale of tmp images, not the final images!!!. 设置中间图片的放大倍数,根据自己需要进行尝试</span> .scale(<span class="pl-c1">3</span>) <span class="pl-c">//select a file or folder. 选择一个文件或者文件夹。</span> .file(<span class="pl-s"><span class="pl-pds">"</span>E:/pptFolder<span class="pl-pds">"</span></span>) <span class="pl-c">//set the compression ratio and it will be invalid once width or height set.</span> <span class="pl-c">//设置压缩比例,注意一旦你设置了宽度或者高度,则该设置无效。</span> .ratio(<span class="pl-c1">0.500</span>) <span class="pl-c">//start the conversion of first page. 开始转换,只转换第一页。</span> .convertFirstPage(); |
Dependencies
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!-- 操作ppt所需依赖 manipulate slideshow --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>4.1.0</version> </dependency> <!-- 压缩图片 compress image --> <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.8</version> </dependency> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
package ink.hansanshi.pptutil; import net.coobird.thumbnailator.Thumbnails; import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.xslf.usermodel.XMLSlideShow; 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.util.ArrayList; import java.util.List; import java.util.UUID; /** * 这是一个工具类,可以将ppt或者pptx文件转换为图片 * * 使用Apache POI将幻灯片转换为图片,但是直接转换的图片质量很低. * 对其进行放大转换后质量会有所改善,但是文件体积也会比较大。 * 所以基本思路是:利用poi放大转换幻灯片--> 利用thumbnailator进行压缩并输出 * @author :hansanshi * @date :Created in 2019/4/29 */ public class PPTToImgConverter { /**支持四种图片格式,jpg,png,bmp,wbmp*/ public static final String JPG = ".jpg"; public static final String PNG = ".png"; public static final String BMP = ".bmp"; public static final String WBMP = ".wbmp"; /**.ppt格式*/ private static final int PPT_FORMAT = 0; /**.pptx格式*/ private static final int PPTX_FORMAT = 1; /**其他文件格式*/ private static final int OTHER_FORMAT = -1; /**输出图片的格式,默认为jpg*/ private String imgFormat = JPG; /**临时图片放大倍数,默认为3*/ private int scale = 3; /**压缩比例,如指定了宽度或者高度,则该值不会生效*/ private Double ratio = 1.00; /**需要转换的文件列表*/ private File[] files; /**输出图片分辨率的宽度*/ private Integer width; /**输出图片分辨率的高度*/ private Integer height; /**设定幻灯片转换的起始页码*/ private int start = 0; /**设定幻灯片转换的结束页码,该页会被转换,如果是负值,代表倒数第几页*/ private int end = -1; /**图片输出目录前缀*/ private File outputDirPrefix; /**设置操作目录*/ public static PPTToImgConverter dir(String dirPrefix){ return new PPTToImgConverter(dirPrefix); } /**选择单个文件或者文件夹*/ public PPTToImgConverter file(String filePath){ return file(new File(filePath)); } /**选择单个文件或者文件夹*/ public PPTToImgConverter file(File file){ return files(new File[]{file}); } /**选择多个文件或者文件夹*/ public PPTToImgConverter files(String[] filePaths){ File[] files = new File[filePaths.length]; for (int i = 0; i < filePaths.length; i++) { files[i] = new File(filePaths[i]); } return files(files); } /**选择多个文件或者文件夹*/ public PPTToImgConverter files(File[] files){ List<File> slideshowFiles = new ArrayList<>(); for (File file:files){ if (file.isDirectory()){ slideshowFiles.addAll(getSlideShowFiles(file)); }else{ if (getFormat(file)>OTHER_FORMAT){ slideshowFiles.add(file); } } } this.files = slideshowFiles.toArray(new File[0]); return this; } /** * 设置临时图片放大倍数,默认为3 * @param scale 临时图片放大倍数 * @return this */ public PPTToImgConverter scale(int scale){ if (scale<=0){ throw new IllegalArgumentException("scale must be positive"); } this.scale = scale; return this; } /** * 设置输出图片分辨率 * @param width 分辨率宽度 * @param height 分辨率高度 * @return this */ public PPTToImgConverter size(int width, int height){ return this.width(width).height(height); } /** * 设置输出图片分辨率宽度 * @param width 分辨率宽度 * @return this */ public PPTToImgConverter width(int width){ if (width<=0){ throw new IllegalArgumentException("width must be positive"); } this.width = width; return this; } /** * 设置输出图片分辨率高度 * @param height 分辨率高度 * @return this */ public PPTToImgConverter height(int height){ if (height<=0){ throw new IllegalArgumentException("height must be positive"); } this.height = height; return this; } /** * 设置输出图片压缩比例,相对于原幻灯片分辨率 * @param ratio 压缩比例 * @return this */ public PPTToImgConverter ratio(double ratio){ if (ratio <= Double.MIN_VALUE){ throw new IllegalArgumentException("ratio must be positive"); } this.ratio = ratio; return this; } /** * 设置转换起始页,从0开始 * @param start 起始页 * @return this */ public PPTToImgConverter from(int start){ this.start = start; return this; } /** * 设置转换结束页,该页也会被转换 * @param end 结束页 * @return this */ public PPTToImgConverter to(int end){ this.end = end; return this; } public PPTToImgConverter imgFormat(String format){ if (JPG.equals(format) ||PNG.equals(format) ||BMP.equals(format) ||WBMP.equals(format)){ this.imgFormat = format; return this; }else{ throw new IllegalArgumentException("Image format not supported"); } } /**开始转换*/ public void convert() { if (start*end > 0 && end<start){ throw new IllegalArgumentException("start position is behind end!"); } this.convertFiles(); } /**只转换第一页*/ public void convertFirstPage(){ this.convertCertainPage(0); } /**只转换最后一页*/ public void convertLastPage(){ this.convertCertainPage(-1); } /**只转换特定一页*/ public void convertCertainPage(int pageNum){ this.from(pageNum) .to(pageNum) .convert(); } /**转换所有页*/ public void convertAllPages(){ this.from(0).to(-1) .convert(); } /** * 调用构造方法,设置输出目录前缀 * @param dirPrefix 输出目录前缀 */ private PPTToImgConverter(String dirPrefix){ this.outputDirPrefix = new File(dirPrefix,"output"); } /** * 转换多个文件并输出转换结果 */ private void convertFiles() { for (File file:files) { File[] outputImgs; try { outputImgs = convertSlideshow(file); } catch (Exception e) { System.out.println(file.getAbsolutePath()+" can't be converted: "+e.getMessage()); continue; } if (outputImgs.length == 0){ System.out.println(file.getAbsolutePath()+" the result of conversion is null"); continue; } System.out.println(file.getAbsolutePath()+" has been converted in: "+outputImgs[0].getParent()); } } /** *转换幻灯片为图片 * @param file 幻灯片文件 * @return File[] 转换的图片文件路径列表 * @throws IOException 多出可能抛出 */ private File[] convertSlideshow(File file) throws IOException { //将文件加载为幻灯片 SlideShow slideShow= getSlideShow(file); //根据设置生成图片 File outputDir = new File(outputDirPrefix,file.getName()); File[] outputImgs = this.generateImg(outputDir,slideShow); return outputImgs; } /** * 获取幻灯片,并根据幻灯片信息设置输出图片的分辨率 * @param file 幻灯片文件 * @return SlideShow 幻灯片 * @throws IOException */ private SlideShow getSlideShow(File file) throws IOException { //根据不同文件格式进行初始化 FileInputStream inputStream = new FileInputStream(file); SlideShow slideShow; int fileFormat = getFormat(file); if (fileFormat == PPTToImgConverter.PPTX_FORMAT){ slideShow = new XMLSlideShow(inputStream); }else if (fileFormat == PPTToImgConverter.PPT_FORMAT){ slideShow = new HSLFSlideShow(inputStream); }else{ inputStream.close(); throw new IOException("Not SlideShow"); } inputStream.close(); return slideShow; } /** * 确定需要的页码并生成对应图片 * @param outputDir 用于存放图片的目录 * @param slideShow 幻灯片 * @return File[] 生成的图片文件列表 * @throws IOException 生成图片时可能抛出 */ private File[] generateImg(File outputDir, SlideShow slideShow) throws IOException { //创建输出目录 while(outputDir.exists()){ outputDir = new File(outputDir.getParent(), UUID.randomUUID().toString()); } outputDir.mkdirs(); //生成每个文件实际的起始和结束位置 //如果start和end的设置值为负的话,表示是是倒数第几页,例-1表示最后一页 List<Slide> slides = slideShow.getSlides(); int realStart = start<0?start+slides.size():start; int realEnd = end<0?end+slides.size():end; //起始点不在范围内或者结束位置不合理 if (realStart<0 || realEnd<0 || realStart>= slides.size() || realStart > realEnd){ return new File[0]; } //只要起始点处于有效范围即可,终点值如超出范围则置为最后一页 if (realEnd >= slides.size()){ realEnd = slides.size()-1 ; } //根据幻灯片的分辨率和预先的设置以生成实际输出图片的分辨率 //一旦设置width和height,则ratio的设置无效 Dimension pageSize = slideShow.getPageSize(); int realWidth; int realHeight; if (width == null){ realHeight = height==null?(int)(pageSize.height*ratio):height; realWidth = height==null?(int)(pageSize.width*ratio):height*pageSize.width/pageSize.height; }else{ realWidth = width; realHeight = height==null? width*pageSize.height/pageSize.width:height; } //放大特定倍数倍以提高图片清晰度,图片文件体积也会随之增大 BufferedImage bufferedImg = new BufferedImage(pageSize.width* scale, pageSize.height* scale,BufferedImage.TYPE_INT_RGB); File[] outputImgs = new File[realEnd-realStart+1]; //开始逐页生成图片 Graphics2D graphics = bufferedImg.createGraphics(); graphics.scale(scale, scale); graphics.setPaint(Color.white); for (int i = realStart; i <= realEnd; i++) { //即用刷填充背景为白色,否则如果ppt背景是透明的话,会有上次绘图留下的背景 graphics.fill(new Rectangle2D.Float(0, 0, pageSize.width * scale, pageSize.height * scale)); slides.get(i).draw(graphics); //压缩并保存为文件 File outputImg = new File(outputDir,i+imgFormat); Thumbnails.of(bufferedImg) .size(realWidth,realHeight) .toFile(outputImg); outputImgs[i-realStart]=outputImg; } return outputImgs; } /** * 检测文件的格式 * @param file 待检测格式的文件 * @return int 文件的格式,分三种情况: OTHER_FORMAT, -1 ;PPT_FORMAT, 0; PPTX_FORMAT, 1 */ private int getFormat(File file) { int format = OTHER_FORMAT; String filename = file.getName(); if (filename.contains(".") ) { String suffix = filename.substring(filename.lastIndexOf(".")).toLowerCase(); if (".ppt".equals(suffix)) { format = PPT_FORMAT; }else if (".pptx".equals(suffix)) { format = PPTX_FORMAT; } } return format; } /** * 递归获取目录及其子目录的幻灯片文件 * @param dir 目录 * @return 幻灯片文件列表 不返回Null */ private List<File> getSlideShowFiles(File dir) { List<File> files=new ArrayList<>(); if (dir.isDirectory()){ File[] subFiles = dir.listFiles(); if (subFiles == null){ return files; } for (File subFile: subFiles) { if (subFile.isDirectory()){ //获取子目录的幻灯片文件 files.addAll(getSlideShowFiles(subFile)); }else{ //检测文件格式,如果是幻灯片,则加入列表中 int result = getFormat(subFile); if (result > OTHER_FORMAT){ files.add(subFile); } } } }else{ int result = getFormat(dir); if (result > OTHER_FORMAT){ files.add(dir); } } return files; } } |
https://github.com/Hansanshi/pptutil