private BufferedImage image;
private int imageWidth = 750; //圖片的寬度
private int imageHeight = 1350; //圖片的高度
@Override
public String queryFindEntityGoodPictureDetail(Long id, Long groupId, Long memberId, String url) throws Exception {
int H_title = 300; //頭部高度
int H_activity = 430; //活動高度
int H_mainPic = 700; //廣告高度
int H_tip = 300; //商品價格欄
int tip_2_top = (H_title+H_mainPic);
MallEntityGood mallEntityGood=mallEntityGoodMapper.queryFindEntityGoodPictureDetail(id,groupId);
image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
//設置圖片的背景色
Graphics2D main = image.createGraphics();
main.setColor(Color.white);
main.fillRect(0, 0, imageWidth, imageHeight);
//***********************頁面頭部
Graphics title = image.createGraphics();
title.setColor(Color.BLACK);
// 設置字體
Font titleFont = new Font("宋體", Font.BOLD, 52);
title.setFont(titleFont);
// 如果商品名大於12個字符,截取12個字符在第一行中顯示,剩余的在第二行顯示
// 完成之后優化 考慮用戶在使用英文的前提下 每行字數乘兩倍
if(mallEntityGood.getName().length()>14) {
String goodName1=mallEntityGood.getName().substring(0,14);
if(mallEntityGood.getName().length()>14 && mallEntityGood.getName().length()<27){
String goodName2=mallEntityGood.getName().substring(14);
title.drawString(URLDecoder.decode(goodName2, "UTF-8"), 20, (H_title)/3+80);
}else if(mallEntityGood.getName().length()>27){
String goodName2=mallEntityGood.getName().substring(14,27);
title.drawString(URLDecoder.decode(goodName2, "UTF-8")+"...", 20, (H_title)/3+80);
}
title.drawString(URLDecoder.decode(goodName1, "UTF-8"), 20, (H_title)/3+5);
}else {
title.drawString(URLDecoder.decode(mallEntityGood.getName(), "UTF-8"), 20, (H_title)/3+5);
}
// 獲取商品所參加的活動
// 標題之下(商品所屬活動)
Graphics activity = image.createGraphics();
activity.setColor(Color.red);
Font activityFont = new Font("宋體", Font.BOLD, 38);
activity.setFont(activityFont);
String goodid=String.valueOf(id);
List<ActivityUnroutine> activityUnroutineList = activityUnroutineMapper.queryActivityListById(goodid);
if(activityUnroutineList != null){
for (int i=0;i<activityUnroutineList.size();i++){
if (StringUtils.isNotEmpty(activityUnroutineList.get(i).getActivityName())){
String activityNames= activityUnroutineList.get(i).getActivityName();
if (activityNames.length()>20){
activity.drawString( "活動:"+URLDecoder.decode(activityNames, "UTF-8").substring(0,21)+"...", 20, (H_activity)/2);
}else {
activity.drawString( "活動:"+URLDecoder.decode(activityNames, "UTF-8"), 20, (H_activity)/2);
}
break;
}
}
}else{
String activityName="";
activity.drawString( activityName, 20, (H_activity)/2);
}
//***********************插入中間廣告圖
Graphics mainPic = image.getGraphics();
BufferedImage bimg = null;
// 獲取商品圖片
if(mallEntityGood.getPicture()!=null) {
String[] picture = mallEntityGood.getPicture().trim().split(",");
for(int i=0;i<picture.length;i++) {
if(picture[i].trim().length()>0){
bimg=ImageIO.read(new URL(picture[i]).openStream());
mainPic.drawImage(bimg, 0, H_title, imageWidth, H_mainPic, null);
mainPic.dispose();
break;
}
}
}
// 價格以及小圖標的排布
Graphics2D tip = image.createGraphics();
tip.setColor(Color.red);
Font tipFont = new Font("宋體", Font.BOLD, 52);
tip.setFont(tipFont);
DecimalFormat df = new DecimalFormat(".00");
tip.drawString("¥"+ df.format(mallEntityGood.getPromotionPrice()/100), 300, tip_2_top+(H_tip)/2-40);
Font btnFont = new Font("宋體", Font.PLAIN, 26);
Graphics2D btn1 = image.createGraphics();
btn1.setColor(Color.red);
btn1.setFont(btnFont);
Graphics mainPic3 = image.getGraphics();
BufferedImage bimg3 = null;
String imgurl3="http://ebank007.oss-cn-hangzhou.aliyuncs.com/20180731173813D9PJ9Q.jpg";
bimg3=ImageIO.read(new URL(imgurl3).openStream());
int width = bimg3.getWidth();
int height = bimg3.getHeight();
mainPic3.drawImage(bimg3, 580, tip_2_top+(H_tip)/2-80, width, height, null);
mainPic3.dispose();
Font btnFont2 = new Font("宋體", Font.PLAIN, 36);
Graphics2D btn2 = image.createGraphics();
btn2.setColor(Color.black);
btn2.setFont(btnFont2);
String salePrice="原價";
btn2.drawString(URLDecoder.decode(salePrice, "UTF-8")+": ¥"+df.format(mallEntityGood.getSalePrice()/100), 300, tip_2_top+(H_tip)/2+30);
btn2.drawString("------------", 300, tip_2_top+(H_tip)/2+30);
// 確定二維碼所在的位置
Graphics2D tip1 = image.createGraphics();
tip1.setColor(Color.black);
Font tipFont2 = new Font("宋體", Font.PLAIN, 28);
tip1.setFont(tipFont2);
String ccLog="長按識別二維碼";
tip1.drawString("["+URLDecoder.decode(ccLog, "UTF-8")+"]", 35, tip_2_top+(H_tip)/2+180);
// 用戶分享鏈接二維碼
String shareGoodQRcode=url+"/api/oAuth2/goodDetailShare?gid="+id+"&"+"memberid="+memberId+"&"+"groupId="+groupId;
int qrcode_height=250;
int qrcode_width=250;
BufferedImage image = createImage1(shareGoodQRcode, qrcode_width, qrcode_height);
// 確定二維碼在圖中的位置
Graphics mainPic1 = this.image.getGraphics();
if(image!=null){
mainPic1.drawImage(image, 20, tip_2_top+30, qrcode_width, qrcode_height, null);
mainPic1.dispose();
}
String uuid = UUID.randomUUID().toString();
createImage(uuid+".png");
// 內存中文件存儲的文件夾的位置
/* File dir=new File(uuid+".png");
File[] lst=dir.listFiles();
for (File f:lst){
// 三天自動清除文件(失效處理)
if (new Date().getTime()-f.lastModified()>24*60*60*1000*3){
f.delete();
}
}*/
File dir=new File(uuid+".png");
if (new Date().getTime()-dir.lastModified()>24*60*60*1000*3){
dir.delete();
}
InputStream in = null;
byte[] data = null;
//讀取圖片字節數組
try {
in = new FileInputStream(uuid+".png");
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
//對字節數組Base64編碼
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data); //返回Base64編碼過的字節數組字符串
// FileImageInputStream input = new FileImageInputStream(new File("1.png"));
// ByteArrayOutputStream output = new ByteArrayOutputStream();
// byte[] buf = new byte[1024];
// int numBytesRead = 0;
// while ((numBytesRead = input.read(buf)) != -1) {
// output.write(buf, 0, numBytesRead);
// }
// byte[] data = output.toByteArray();
// output.close();
// input.close();
// return data;
}
/**
* 二維碼圖片的生成
* @param content 鏈接
* @param qrcode_width 二維碼寬
* @param qrcode_height 二維碼高
* @return
* @throws Exception
*/
public static BufferedImage createImage1(String content, int qrcode_width, int qrcode_height) throws Exception {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, qrcode_width, qrcode_height, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
: 0xFFFFFFFF);
}
}
return image;
}
//生成圖片文件
@SuppressWarnings("restriction")
public void createImage(String fileLocation) {
BufferedOutputStream bos = null;
if(image != null) {
try {
FileOutputStream fos = new FileOutputStream(fileLocation);
bos = new BufferedOutputStream(fos);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
encoder.encode(image);
fos.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {//關閉輸出流
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
需要注意的是:后台數據合成的圖片后 返回Base64 String時 前端微信顯示會出現中文亂碼
這一點是因為,開發時window本地下,系統中含有宋體.楷體等資源,而在服務器上
是沒有這些字體的需要導入TTF相匹配的肢體文件,之后重啟nginx中tomcat.
還有一點:后台代碼中調用方法生成的圖片,並不是保存到本地,還是服務器內存需要定時清除