java Graphics2D 画图

  

  

平时出图都是前端画图的,本次画图是对响应时间有要求,所有给后端提的需求。这里就给出一个demo 还有列出其中遇到的几个小问题

1 首先列出结果图

 

 

 

 

 

2   遇到的问题

  1  这是两张图片覆盖的。

  coverImage 方法  

     2  覆盖图是圆角矩形,但是四个角的底色要和底图保持一致

  需要先fillRect 填充相应的底色。

     3  覆盖图的文字显示问题, 因为是介绍,不确定字体的多少  自动换行  多行文字 自动计算高度  我这个是标题最多2行     介绍最多3行(在方法里面都是参数)。  

 

  drawString  该方法从网上找的  自己改造了下   

     4  font 字体的问题  和 Color颜色的问题

        font字体  从C:\Windows\Fonts 中找对应的字体就行   Font font3 = new Font("苹方-简", Font.BOLD, 28);    但是记得如果是奇葩字体 比如我这个要求苹果的字体  一定要把字体上传到linux服务器  否咋 测试或生成 文字就会变成 “口口”

      Color   颜色  java api 不能识别  #CC00FF   只能识别    Color.getHSBColor(153,153,153)

https://www.sioe.cn/yingyong/yanse-rgb-16/  这个百度颜色转化  就出来了

 

 5 推荐一个好使的颜色取色器

链接:https://pan.baidu.com/s/1gxLTOIysfYQLlSWdMFmYpQ
提取码:se9s

3  main 代码  

public static void main(String[] args) throws Exception {
  int picWid=660;
  int picHeight1=269;
  int picHeight2=531;
  BufferedImage BufImage = new BufferedImage(picWid, picHeight1+picHeight2, BufferedImage.TYPE_INT_RGB);// RGB形式
  Graphics2D g = BufImage.createGraphics();
  g.drawRect(0,0,picWid,picHeight1);//画线框
  g.setColor(Color.red);
  g.fillRect(0,0,picWid,picHeight1);//是用预定的颜色填充一个矩形


  g.drawRect(0,picHeight1,picWid,picHeight2);//画线框
  g.setColor(Color.white);
  g.fillRect(0,picHeight1,picWid,picHeight2);//是用预定的颜色填充一个矩形

  // 设置圆形头像
  BufferedImage headImage = ImageIO.read(new       URL("https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKu4BoQkiauW80hPgpeLZSVkHXVDVY1iaQkicNj5UjY5w1DDqZqk6GnfedKPthqxdE4qK2K2wCUTMoUw/132"));
  headImage=convertCircular(headImage);


  // 获取小程序码
  BufferedImage qrCodeImage = ImageIO.read(new URL("https://sxhw-1251808348.cos.ap-beijing.myqcloud.com/xcxqrcode/2020-  04/af12e742bcf7662706f2c0153f0e82d8.jpg"));
  // 设置各组件位置
  //设置头像
  g.drawImage(headImage, 48, 32, 80, 80, null);
  //小程序码
  g.drawImage(qrCodeImage, 30, 620, 160, 160, null);

  //写字
  g.setColor(Color.white);
  Font font2 = new Font("苹方-简", Font.BOLD, 24);
  g.setFont(font2);
  g.drawString("丁一江", 148, 53);

  //写字
  g.setColor(Color.white);
  Font font3 = new Font("苹方-简", Font.BOLD, 28);
  g.setFont(font3);
  g.drawString("我的团购活动正在火热进行~", 148, 90);

  //写字
  g.setColor(Color.black);
  Font font4 = new Font("苹方-简", Font.BOLD, 32);
  g.setFont(font4);
  g.drawString("长按识别下程序码", 210, 677);

  //写字
  g.setColor(Color.getHSBColor(153,153,153));
  Font font5 = new Font("苹方-简", Font.BOLD, 24);
  g.setFont(font5);
  g.drawString("立即抢购好物", 210, 730);

  //覆盖层数据
  BufferedImage realImg = new BufferedImage(620, 456, BufferedImage.TYPE_INT_RGB);// RGB形式
  Graphics2D real2D = realImg.createGraphics();

  // real2D.drawRect(0,0,710,100);//画线框
  //解决 圆角矩形 4个角黑色 先填充颜色 在画矩形
  real2D.setColor(Color.red);
  real2D.fillRect(0,0,620,125);//是用预定的颜色填充一个矩形


  //real2D.drawRect(0,100,710,400);//画线框
  real2D.setColor(Color.white);
  real2D.fillRect(0,125,620,331);//是用预定的颜色填充一个矩形


  real2D.setColor(Color.white);
  real2D.fillRoundRect(0, 0, 620, 456,40, 40);


  //商品介绍
  String groupName="商品标题test-商品标题test-商品标题test-商品标题test-商品标题test-商品标题test-商品标题test-商品标题test-商品标题test";
  String groupDetail="商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test-商品详情test";
  String price="商品团购价:¥5-¥28.8";


  //写字
  real2D.setColor(Color.black);
  Font font6 = new Font("苹方-简", Font.BOLD, 28);
  int height=drawString(real2D,font6,groupName,578,20,40,30,2);

  //写字
  real2D.setColor(Color.gray);
  Font font7 = new Font("苹方-简", Font.BOLD, 20);
  height=drawString(real2D,font7,groupDetail,578,20,height+20,30,3);

  //写字
  real2D.setColor(Color.red);
  Font font8 = new Font("苹方-简", Font.BOLD, 28);
  height=drawString(real2D,font8,price,578,20,height+40,30,1);
  // 商品图片
  List<String> imgList=new ArrayList<String>();
  imgList.add("https://sxhw-1251808348.cos.ap-beijing.myqcloud.com/prod-image/2020-04/22824b828c39aec9396fe345cc2d8cb0.jpg");
  imgList.add("https://sxhw-1251808348.cos.ap-beijing.myqcloud.com/prod-image/2020-04/3c4dbfef1fbe4c8ae092e0efc79ecb8c.jpg");
  imgList.add("https://sxhw-1251808348.cos.ap-beijing.myqcloud.com/prod-image/2020-04/0a5774763ea977d5421b08b8204a0ed7.jpg");
  for(int i=0;i<imgList.size();i++) {
    String imgUrl=imgList.get(i);
    BufferedImage posterBufImage = ImageIO.read(new URL(imgUrl));
    real2D.drawImage(posterBufImage, 180*i+(i+1)*20, height, 180, 179, null);
  }

  // 两张图片覆盖
  BufImage = coverImage(BufImage, realImg, 20, 144, 620, 456);

  // g.setColor(Color.blue);
  ImageIO.write(BufImage, "png", new File("D:\\1111test\\demo31.png"));
}

   

 

/**
* 文字超出限定长度自动换行
*
* @param g 画布
* @param font 字体样式
* @param text 文字
* @param widthLength 最大长度 (多少长度后需要换行)
* @param x 文字位置坐标 x
* @param y 文字位置坐标 Y
* @param yn 每次换行偏移多少pt
* showLine 显示行数 文字可能过多 我们只显示showLine行文字
*/
private static int drawString(Graphics2D g, Font font, String text1, int widthLength, int x, int y, int yn,int showLine) {
  FontMetrics fg = g.getFontMetrics(font);
  List<String> ls = new ArrayList<>();
  getListText(fg, text1, widthLength, ls);
  g.setFont(font);
  for (int i = 0; i < ls.size(); i++) {
    if(i==showLine) {
      break;
    }
    if (i == 0) {
      g.drawString(ls.get(i), x, y);
    } else {
      g.drawString(ls.get(i), x, y + i*yn);
    }
  }
  int height=fg.getHeight();
  if(ls.size()<=showLine) {
    y=y+height*ls.size();
  }else {
    y=y+height*showLine;
  }
  return y;
}

 

/**
* 递归 切割字符串
* @param fg
* @param text
* @param widthLength
* @param ls
*/
private static void getListText(FontMetrics fg, String text, int widthLength, List<String> ls) {
  String ba = text;
  boolean b = true;
  int i = 1;
  while (b) {
    if (fg.stringWidth(text) > widthLength) {
      text = text.substring(0, text.length() - 1);
      i++;
    } else {
      b = false;
    }
  }
  if (i != 1) {
    ls.add(ba.substring(0, ba.length() - i));
    getListText(fg, ba.substring(ba.length() - i), widthLength, ls);
  } else {
    ls.add(text);
  }
}

 

 

//覆盖图片方法
public static BufferedImage coverImage(BufferedImage baseBufferedImage, BufferedImage coverBufferedImage, int x, int y, int width, int height) throws Exception{
  // 创建Graphics2D对象,用在底图对象上绘图
  Graphics2D g2d = baseBufferedImage.createGraphics();
  // 绘制
  g2d.drawImage(coverBufferedImage, x, y, width, height, null);
  g2d.dispose();// 释放图形上下文使用的系统资源
  return baseBufferedImage;
}

 

 

/**
* 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的
*
* @param url
* 用户头像地址
* @return
* @throws IOException
*/
public static BufferedImage convertCircular(BufferedImage bi1) throws IOException {

  // BufferedImage bi1 = ImageIO.read(new File(url));

  // 这种是黑色底的
  // BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_INT_RGB);

  // 透明底的图片
  BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
  Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1.getHeight());
  Graphics2D g2 = bi2.createGraphics();
  g2.setClip(shape);
  // 使用 setRenderingHint 设置抗锯齿
  g2.drawImage(bi1, 0, 0, null);
  // 设置颜色
  g2.setBackground(Color.green);
  g2.dispose();
  return bi2;
}

 

posted @ 2020-05-07 15:31  丁一江  阅读(2691)  评论(0编辑  收藏  举报