最近有負責微信開發,對于微信開發的項目,肯定少不了二維碼啦,正好有個這樣的需求,這對不同的商品生成一個二維碼,掃碼即刻下單。博主就弄了一個二維碼生成的工具類。
弄出來之后,產品經理又說了,中間放上公司的logo是不是好一點?加上吧,
加上公司logo之后,產品經理想了想,每個商品都有個二維碼,銷售人員有很多個商品二維碼,群發給用戶,在qq群上,微信群上,怎么知道哪個二維碼對應哪個商品的呢?于是決定要加上商品名稱。最后商品二維碼就成了下面這個模樣了(當然啦,這里面的logo并不是博主現職公司的)。
效果已經出來啦,下面附上代碼啦
如果讀者不需要logo或者二維碼名稱的,讀懂代碼后進行刪減即可。注釋多多,還是很容易看懂的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
|
package com.luo.wctweb.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.lz.lsf.util.Base64; /** * @Description: (二維碼) * @author:luoguohui * @date:2015-10-29 下午05:27:13 */ public class ZXingCode { private static final int QRCOLOR = 0xFF000000 ; //默認是黑色 private static final int BGWHITE = 0xFFFFFFFF ; //背景顏色 public static void main(String[] args) throws WriterException { try { getLogoQRCode( "https://www.baidu.com/" , null , "跳轉到百度的二維碼" ); } catch (Exception e) { e.printStackTrace(); } } /** * 生成帶logo的二維碼圖片 * * @param qrPic * @param logoPic */ public static String getLogoQRCode(String qrUrl,HttpServletRequest request,String productName) { // String filePath = request.getSession().getServletContext().getRealPath("/") + "resources/images/logoImages/llhlogo.png"; //filePath是二維碼logo的路徑,但是實際中我們是放在項目的某個路徑下面的,所以路徑用上面的,把下面的注釋就好 String filePath = "C:/Users/luoguohui/Desktop/78310a55b319ebc4fa3aef658126cffc1f17168f.jpg" ; //TODO String content = qrUrl; try { ZXingCode zp = new ZXingCode(); BufferedImage bim = zp.getQR_CODEBufferedImage(content, BarcodeFormat.QR_CODE, 400 , 400 , zp.getDecodeHintType()); return zp.addLogo_QRCode(bim, new File(filePath), new LogoConfig(), productName); } catch (Exception e) { e.printStackTrace(); } return null ; } /** * 給二維碼圖片添加Logo * * @param qrPic * @param logoPic */ public String addLogo_QRCode(BufferedImage bim, File logoPic, LogoConfig logoConfig, String productName) { try { /** * 讀取二維碼圖片,并構建繪圖對象 */ BufferedImage image = bim; Graphics2D g = image.createGraphics(); /** * 讀取Logo圖片 */ BufferedImage logo = ImageIO.read(logoPic); /** * 設置logo的大小,本人設置為二維碼圖片的20%,因為過大會蓋掉二維碼 */ int widthLogo = logo.getWidth( null )>image.getWidth()* 3 / 10 ?(image.getWidth()* 3 / 10 ):logo.getWidth( null ), heightLogo = logo.getHeight( null )>image.getHeight()* 3 / 10 ?(image.getHeight()* 3 / 10 ):logo.getWidth( null ); /** * logo放在中心 */ int x = (image.getWidth() - widthLogo) / 2 ; int y = (image.getHeight() - heightLogo) / 2 ; /** * logo放在右下角 * int x = (image.getWidth() - widthLogo); * int y = (image.getHeight() - heightLogo); */ //開始繪制圖片 g.drawImage(logo, x, y, widthLogo, heightLogo, null ); // g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15); // g.setStroke(new BasicStroke(logoConfig.getBorder())); // g.setColor(logoConfig.getBorderColor()); // g.drawRect(x, y, widthLogo, heightLogo); g.dispose(); //把商品名稱添加上去,商品名稱不要太長哦,這里最多支持兩行。太長就會自動截取啦 if (productName != null && !productName.equals( "" )) { //新的圖片,把帶logo的二維碼下面加上文字 BufferedImage outImage = new BufferedImage( 400 , 445 , BufferedImage.TYPE_4BYTE_ABGR); Graphics2D outg = outImage.createGraphics(); //畫二維碼到新的面板 outg.drawImage(image, 0 , 0 , image.getWidth(), image.getHeight(), null ); //畫文字到新的面板 outg.setColor(Color.BLACK); outg.setFont( new Font( "宋體" ,Font.BOLD, 30 )); //字體、字型、字號 int strWidth = outg.getFontMetrics().stringWidth(productName); if (strWidth > 399 ) { // //長度過長就截取前面部分 // outg.drawString(productName, 0, image.getHeight() + (outImage.getHeight() - image.getHeight())/2 + 5 ); //畫文字 //長度過長就換行 String productName1 = productName.substring( 0 , productName.length()/ 2 ); String productName2 = productName.substring(productName.length()/ 2 , productName.length()); int strWidth1 = outg.getFontMetrics().stringWidth(productName1); int strWidth2 = outg.getFontMetrics().stringWidth(productName2); outg.drawString(productName1, 200 - strWidth1/ 2 , image.getHeight() + (outImage.getHeight() - image.getHeight())/ 2 + 12 ); BufferedImage outImage2 = new BufferedImage( 400 , 485 , BufferedImage.TYPE_4BYTE_ABGR); Graphics2D outg2 = outImage2.createGraphics(); outg2.drawImage(outImage, 0 , 0 , outImage.getWidth(), outImage.getHeight(), null ); outg2.setColor(Color.BLACK); outg2.setFont( new Font( "宋體" ,Font.BOLD, 30 )); //字體、字型、字號 outg2.drawString(productName2, 200 - strWidth2/ 2 , outImage.getHeight() + (outImage2.getHeight() - outImage.getHeight())/ 2 + 5 ); outg2.dispose(); outImage2.flush(); outImage = outImage2; } else { outg.drawString(productName, 200 - strWidth/ 2 , image.getHeight() + (outImage.getHeight() - image.getHeight())/ 2 + 12 ); //畫文字 } outg.dispose(); outImage.flush(); image = outImage; } logo.flush(); image.flush(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.flush(); ImageIO.write(image, "png" , baos); //二維碼生成的路徑,但是實際項目中,我們是把這生成的二維碼顯示到界面上的,因此下面的折行代碼可以注釋掉 //可以看到這個方法最終返回的是這個二維碼的imageBase64字符串 //前端用 <img src="data:image/png;base64,${imageBase64QRCode}"/> 其中${imageBase64QRCode}對應二維碼的imageBase64字符串 ImageIO.write(image, "png" , new File( "C:/Users/luoguohui/Desktop/TDC-" + new Date().getTime() + "test.png" )); //TODO String imageBase64QRCode = Base64.byteArrayToBase64(baos.toByteArray()); baos.close(); return imageBase64QRCode; } catch (Exception e) { e.printStackTrace(); } return null ; } /** * 構建初始化二維碼 * * @param bm * @return */ public BufferedImage fileToBufferedImage(BitMatrix bm) { BufferedImage image = null ; try { int w = bm.getWidth(), h = bm.getHeight(); image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); for ( int x = 0 ; x < w; x++) { for ( int y = 0 ; y < h; y++) { image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFCCDDEE ); } } } catch (Exception e) { e.printStackTrace(); } return image; } /** * 生成二維碼bufferedImage圖片 * * @param content * 編碼內容 * @param barcodeFormat * 編碼類型 * @param width * 圖片寬度 * @param height * 圖片高度 * @param hints * 設置參數 * @return */ public BufferedImage getQR_CODEBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height, Map<EncodeHintType, ?> hints) { MultiFormatWriter multiFormatWriter = null ; BitMatrix bm = null ; BufferedImage image = null ; try { multiFormatWriter = new MultiFormatWriter(); // 參數順序分別為:編碼內容,編碼類型,生成圖片寬度,生成圖片高度,設置參數 bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints); int w = bm.getWidth(); int h = bm.getHeight(); image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); // 開始利用二維碼數據創建Bitmap圖片,分別設為黑(0xFFFFFFFF)白(0xFF000000)兩色 for ( int x = 0 ; x < w; x++) { for ( int y = 0 ; y < h; y++) { image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE); } } } catch (WriterException e) { e.printStackTrace(); } return image; } /** * 設置二維碼的格式參數 * * @return */ public Map<EncodeHintType, Object> getDecodeHintType() { // 用于設置QR二維碼參數 Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(); // 設置QR二維碼的糾錯級別(H為最高級別)具體級別信息 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 設置編碼方式 hints.put(EncodeHintType.CHARACTER_SET, "utf-8" ); hints.put(EncodeHintType.MARGIN, 0 ); hints.put(EncodeHintType.MAX_SIZE, 350 ); hints.put(EncodeHintType.MIN_SIZE, 100 ); return hints; } } class LogoConfig { // logo默認邊框顏色 public static final Color DEFAULT_BORDERCOLOR = Color.WHITE; // logo默認邊框寬度 public static final int DEFAULT_BORDER = 2 ; // logo大小默認為照片的1/5 public static final int DEFAULT_LOGOPART = 5 ; private final int border = DEFAULT_BORDER; private final Color borderColor; private final int logoPart; /** * Creates a default config with on color {@link #BLACK} and off color * {@link #WHITE}, generating normal black-on-white barcodes. */ public LogoConfig() { this (DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART); } public LogoConfig(Color borderColor, int logoPart) { this .borderColor = borderColor; this .logoPart = logoPart; } public Color getBorderColor() { return borderColor; } public int getBorder() { return border; } public int getLogoPart() { return logoPart; } } |
需要說明的是以上代碼依賴了com.google.zxing這個插件,如果讀者跟博主一樣都是使用maven的話,添加下面依賴即可。
如果沒有用maven的話,直接在http://maven.outofmemory.cn/com.google.zxing/core/3.1.0/ 下載。
1
2
3
4
5
|
< dependency > < groupId >com.google.zxing</ groupId > < artifactId >core</ artifactId > < version >3.1.0</ version > </ dependency > |
以上就是Java生成中間logo的二維碼的示例代碼的詳細內容,更多關于Java生成中間logo的二維碼的資料請關注服務器之家其它相關文章!
原文鏈接:https://www.kancloud.cn/digest/javaxviii/126763