java - 如何使用 apache poi 将背景图像设置为居中
问题描述
例如:
幻灯片尺寸:950 x 510
图像尺寸:500 x 4620
这是我的代码
XSLFPictureData idx = ppt.addPicture(file, pictureType);
CTBackgroundProperties bgPr = this.slide.getXmlObject().getCSld().addNewBg().addNewBgPr();
CTBlipFillProperties blipPr = bgPr.addNewBlipFill();
CTBlip blib = blipPr.addNewBlip();
CTRelativeRect ctRelativeRect = blipPr.addNewStretch().addNewFillRect();
double imgHeight = idx.getImageDimensionInPixels().getHeight();
double imgWidth = idx.getImageDimensionInPixels().getWidth();
double pptHeight = ppt.getPageSize().getHeight();
double pptWidth = ppt.getPageSize().getWidth();
if (pptHeight - imgHeight < 0) {
//How to calculate the offset above and below the image
ctRelativeRect.setT(?);
ctRelativeRect.setB(?);
}else if(pptWidth - imgWidth < 0) {
//
ctRelativeRect.setR(?);
ctRelativeRect.setL(?);
}
RelationPart rp = slide.addRelation(null, XSLFRelation.IMAGES, idx);
blib.setEmbed(rp.getRelationship().getId());
我不知道如何计算图像的偏移量,可以使它居中。请给我一些建议。
这是图像: 在此处输入图像描述
这是我想要的效果: 在此处输入图像描述
解决方案
之所以CTRelativeRect
命名为相对,是因为它的尺寸是幻灯片高度和幻灯片宽度的百分比。您的长图像将被拉伸或压缩到这些百分比尺寸。此外,左、右、顶部和底部的所有偏移量都以幻灯片高度和幻灯片宽度的百分比表示。
根据您显示的所需效果,图像应填充整个幻灯片宽度。所以图片宽度将从500px拉伸到950px。这是 950/500 的比率。以相同的比例,高度也会被拉伸。
知道了这一点,我们需要计算图片尺寸从像素到幻灯片尺寸的百分比。知道这一点后,我们可以将顶部偏移量计算为 (100% - 图片高度,以 % 为单位) / 2。如果设置了相同的底部偏移量,则长图片的确切中间将显示在幻灯片背景中。如果顶部偏移量是 (100% - 图片高度,%) / 2) - 100%,底部偏移量是 (100% - 图片高度,%) / 2 + 100%,则幻灯片背景显示长中间以下 1 个幻灯片高度图片。
除此之外,Microsoft
总是会考虑到它自己奇怪的测量单位。由于避免了百分比的浮点数,因此此处的测量单位为千分之一。
例子:
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.*;
import org.openxmlformats.schemas.presentationml.x2006.main.*;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import java.awt.Dimension;
public class CreatePPTXSheetsBackgroundPicture {
public static void main(String[] args) throws Exception {
XMLSlideShow slideShow = new XMLSlideShow();
XSLFPictureData pictureData = slideShow.addPicture(new FileInputStream("2hGsR.jpg"), PictureData.PictureType.JPEG);
slideShow.setPageSize(new Dimension(950, 510));
double imgHeight = pictureData.getImageDimensionInPixels().getHeight();
double imgWidth = pictureData.getImageDimensionInPixels().getWidth();
double sildeHeight = slideShow.getPageSize().getHeight();
double slideWidth = slideShow.getPageSize().getWidth();
//How to calculate the offset above and below the image
// imgWidth stretched to slideWidth => ratio = slideWidth / imgWidth
double ratio = slideWidth / imgWidth;
// sildeHeight% = 100%
// imgHeight% = (imgHeight * ratio) * 100% / sildeHeight
double imgHeightPerCent = (imgHeight * ratio) * 100 / sildeHeight;
// topMiddle% = (100% - imgHeight%) / 2
// bottomMiddle% = (100% - imgHeight%) / 2
// topMiddle+1slideHeight% = (100% - imgHeight%) / 2) - 100%
// bottomMiddle+1slideHeight% = (100% - imgHeight%) / 2 + 100%
// topMiddle-1slideHeight% = (100% - imgHeight%) / 2) + 100%
// bottomMiddle-1slideHeight% = (100% - imgHeight%) / 2 - 100%
// first slide
XSLFSlide slide = slideShow.createSlide();
CTBackgroundProperties backgroundProperties = slide.getXmlObject().getCSld().addNewBg().addNewBgPr();
CTBlipFillProperties blipFillProperties = backgroundProperties.addNewBlipFill();
CTRelativeRect ctRelativeRect = blipFillProperties.addNewStretch().addNewFillRect();
// first slide shows 1 slide above middle of long picture
// measurement unit is thousandth => percent * 1000
int top = (int)Math.round(((100 - imgHeightPerCent) / 2 + 100) * 1000);
int bottom = (int)Math.round(((100 - imgHeightPerCent) / 2 -100) * 1000);
ctRelativeRect.setT(top);
ctRelativeRect.setB(bottom);
String idx = slide.addRelation(null, XSLFRelation.IMAGES, pictureData).getRelationship().getId();
CTBlip blib = blipFillProperties.addNewBlip();
blib.setEmbed(idx);
// second slide
slide = slideShow.createSlide();
backgroundProperties = slide.getXmlObject().getCSld().addNewBg().addNewBgPr();
blipFillProperties = backgroundProperties.addNewBlipFill();
ctRelativeRect = blipFillProperties.addNewStretch().addNewFillRect();
// second slide shows middle of long picture
top = (int)Math.round(((100 - imgHeightPerCent) / 2) * 1000);
bottom = (int)Math.round(((100 - imgHeightPerCent) / 2) * 1000);
ctRelativeRect.setT(top);
ctRelativeRect.setB(bottom);
idx = slide.addRelation(null, XSLFRelation.IMAGES, pictureData).getRelationship().getId();
blib = blipFillProperties.addNewBlip();
blib.setEmbed(idx);
// third slide
slide = slideShow.createSlide();
backgroundProperties = slide.getXmlObject().getCSld().addNewBg().addNewBgPr();
blipFillProperties = backgroundProperties.addNewBlipFill();
ctRelativeRect = blipFillProperties.addNewStretch().addNewFillRect();
// third slide shows 1 slide below middle of long picture
top = (int)Math.round(((100 - imgHeightPerCent) / 2 - 100) * 1000);
bottom = (int)Math.round(((100 - imgHeightPerCent) / 2 + 100) * 1000);
ctRelativeRect.setT(top);
ctRelativeRect.setB(bottom);
idx = slide.addRelation(null, XSLFRelation.IMAGES, pictureData).getRelationship().getId();
blib = blipFillProperties.addNewBlip();
blib.setEmbed(idx);
FileOutputStream out = new FileOutputStream("CreatePPTXSheetsBackgroundPicture.pptx");
slideShow.write(out);
out.close();
}
}
第二张幻灯片显示了您的长图的中间,如您想要的效果所述。
暗示:
整个效果只能使用查看PowerPoint
。Impress
无法显示该效果。并且PowerPoint 2007
可以使用小于 0% 和/或大于 100% 的偏移量来显示效果,但不能设置小于 0% 和/或大于 100% 的偏移量。
推荐阅读
- kubernetes - 有没有办法从 Kubernetes 中的服务对象获取活动日志?
- javascript - 如何获取动态对象键并使用它?
- django - Django ORM 为缺少的日期填充 0
- php - 在 RHEL 7.9 中加载 oci8.so 和 odbc.so 动态库时出错
- jquery - 使用 jQuery 修复导航菜单
- sql - “您无法添加或更改记录,因为表中需要相关记录”
- excel - 如何多选工作表
- kubernetes - 具有 nexus 不安全注册表的 GKE Containerd 节点池
- postgresql - 带有 Postgres 数据库的 WSO2 API-Manager 无法正常工作
- android - 谷歌智能锁是否有任何日期被谷歌身份服务取代,即谷歌一键式?