平時出圖都是前端畫圖的,本次畫圖是對響應時間有要求,所有給后端提的需求。這里就給出一個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;
}