freemarker导出word文档对图片拉伸或拉长的处理

最近因为java项目中有大量的图片需要导出到word(采用freemarker导出模板),导出的过程中发现一个问题:导出饼图的时候会随着浏览器的大小不同被拉长或者拉伸,查阅很多质料但网上并没有找到相关的解决办法,因此今日记录下来以便以后查阅,同时也将解决思路分享给大家,有问题的地方希望有机会看到文章的技术大咖给以指导。
 
1、要点及思路
 
(1)word模板修改后将如果图片的单位是厘米则修改为像素(修改方法网上有)或者自己算出对应的像素,且以下计算已像素为准
 
(2)word文档另存为xml文件,此时打开可看到图片的一些设置 关键行<a:ext cx="1501775" cy="1365250" />设置图片的宽高
 
(3)cx,cy计算公式如下
  公式:实际width=cX*100/914400;//固定系数
            实际height=cY*100/914400;//固定系数
 
(4)java项目将图片放大或缩小的的思路是获取图片宽度和高度,乘以倍数得出新的宽度和高度
 
因此解决该问题的思路转换为
第一步:前端获取实际图片的宽度高度传入后台,当然也可以java直接是获取图片文件
 
第二步:传入设置宽度和高度,即是上面提到的word里图片设置的像素
 
第二步:根据实际宽度高度和设置宽度高度计算缩放比例,得出目标宽度高度
 
第四步:根据以上公式,实际wideth即是现在的目标宽度,高度一样的,计算出目标CX,CY
 
第五步:将该CX,CY套入xml文件关键行 ,即是<a:ext cx="${目标宽度CX}" cy="${目标高度CY}" />
 
此时你可能会发现,如果本来实际宽度和实际高度已经小于设置宽度和高度,图片会被缩放的很小,因此,再对小于设置宽度或高度的图片做等比放大,以宽度位置还是高度位置取决于你自己因此:
 
第六步:选择性的等比放大目标宽度和高度,放大到合适大小
 
 
2、具体代码如下:
 
/**
  * 设置图片宽高(以纸张设置A4为标准,宽高单位像素)
  * @param imWidth 实际宽度
  * @param imHeight 实际高度
  * @param sWidth 设置宽度
  * @param sHeight 设置 
*@param iType 图片类型 已混搭图 和饼图为例
  * @param isEnlarge 是否放大 0-不放大,1-放大 选择性的放大图片
  * @remarks 当 实际宽高小于目标设置宽高时等比缩小后word展示的图片过小,此时下可设置等比放大,放大到合适大小
  * @return
  */ 
 public static Map<String,Object> setWH(String imWidth,String imHeight ,String sWidth,String sHeight,String iType,String isEnlarge){
   Map<String,Object> map=new HashMap<String,Object>();
  //设置宽高
  double width =Double.parseDouble(sWidth);
  double height=Double.parseDouble(sHeight);
  //实际宽高
  double iWidth=Double.parseDouble(imWidth);
  double iHeight=Double.parseDouble(imHeight);
  //目标宽高
  Double tW; 
  Double tH;
  
  //混搭图宽度比例以0.6作为分界点,小于0.6 会拉长,大于0.6会拉伸,饼图:大于0.7小于1.0时会拉长,大于1.0时会拉伸,次临界点以不同大小屏幕测试得出的计算值
  if((width/iWidth<0.6 && "1".equals(imageType)) || (width/iWidth>0.7 && width/iWidth<1.0 && "2".equals(imageType))){
   //计算缩放比例
   tW=iWidth*(height/iHeight);  
   tH=iHeight*(height/iHeight); 
  }else{
   //计算缩放比例
   if(width/iWidth<=height/iHeight){     
    tW=iWidth*(width/iWidth); 
    tH=iHeight*(height/iHeight);    
   }else{   
    tW=iWidth*(height/iHeight);  
    tH=iHeight*(height/iHeight); 
   }
   //选择性的等比放大图片
   if("1".equals(isEnlarge)){
    //目标宽度或高度小于设置宽度或高度时比例方法
    if(tW<width || tH<height){
     map=enlWH(tW,tH,width,height);
     tW=(Double) map.get("tW");
     tH=(Double)map.get("tH");
    }
   }
  
  }
  
  //图片cX,cY计算
  //914400为固定系数
  
  map.put("imageWidth", String.valueOf(tW.intValue()*914400/100));
  map.put("imageHeight",String.valueOf((tH.intValue()*914400/100)));
  return map;
 }
 
 /**
  * 比例放大
  * @param width 转换过的宽度
  * @param height 转换过的高度
  * @param MaxWidth 目标宽度
  * @param MaxHeight 目标高度
  */
 public static Map<String,Object> enlWH(double width,double height,double maxWidth,double maxHeight){
  Map<String, Object> map = Maps.newConcurrentMap();
   // 放大倍数
  double times = 1;
  //比例
  double sw = (maxWidth * 1.0) / (width * 1.0);
  double sh = (maxHeight * 1.0) / (height * 1.0);
  if (width > maxWidth && height > maxHeight) {
   return map;
  } else if (width < maxWidth && height <= maxHeight) {
   if (sw > sh) {
    times = sw + 0.2;//根据实际情况设置
   } else {
    times = sh + 0.2;
   }
  } else if (width < maxWidth && height > maxHeight) {
   times = sw + 0.2;
  } else {
   times = sh + 0.2;
  }
  NumberFormat nf=NumberFormat.getNumberInstance(); 
  nf.setMaximumFractionDigits(1);
  times=Double.parseDouble(nf.format(times));
  Double lastW = times * width;
  Double lastH = times * height;
  map.put("tW", lastW);
  map.put("tH", lastH);
  return map;
 }
 
 
第一次发表经验,以上只是解决此类问题的一个思路,但不是唯一办法,如有好的方案及思路很感谢一起分享出来,写的有不好地方敬请指正!
 
 
 
 
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhouyiddd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值