Java代碼生成內嵌圖片的二維碼


1.首先引入maven依賴: 

 1      <dependency>
 2             <groupId>com.google.zxing</groupId>
 3             <artifactId>core</artifactId>
 4             <optional>true</optional>
 5         </dependency>
 6         <dependency>
 7             <groupId>com.google.zxing</groupId>
 8             <artifactId>javase</artifactId>
 9             <optional>true</optional>
10         </dependency> 

2.直接上代碼:

  1 package itfeng.util;
  2 
  3 import java.awt.Color;
  4 import java.awt.Graphics2D;
  5 import java.awt.Image;
  6 import java.awt.geom.AffineTransform;
  7 import java.awt.image.AffineTransformOp;
  8 import java.awt.image.BufferedImage;
  9 import java.io.File;
 10 import java.io.IOException;
 11 import java.io.OutputStream;
 12 import java.net.HttpURLConnection;
 13 import java.net.URL;
 14 import java.nio.file.Path;
 15 import java.util.HashMap;
 16 import java.util.Hashtable;
 17 
 18 import javax.imageio.ImageIO;
 19 
 20 import com.google.zxing.BarcodeFormat;
 21 import com.google.zxing.BinaryBitmap;
 22 import com.google.zxing.DecodeHintType;
 23 import com.google.zxing.EncodeHintType;
 24 import com.google.zxing.MultiFormatReader;
 25 import com.google.zxing.MultiFormatWriter;
 26 import com.google.zxing.Result;
 27 import com.google.zxing.WriterException;
 28 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
 29 import com.google.zxing.client.j2se.MatrixToImageWriter;
 30 import com.google.zxing.common.BitMatrix;
 31 import com.google.zxing.common.HybridBinarizer;
 32 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 33 
 34 public class QRcodeUtil {
 35 
 36     //注意:圖片的寬度和高度占比會影響生成的二維碼內容是否解析成功
 37     private static final int IMAGE_WIDTH = 120;
 38 
 39     private static final int IMAGE_HEIGHT = 120;
 40 
 41     private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
 42 
 43     private static final int FRAME_WIDTH = 0;
 44 
 45     private static final String IMAGE_FORMAT = "jpg";
 46 
 47     //二維碼外邊距
 48     private static final int IMAGE_MARGIN = 0;
 49 
 50     private static final String CHARSET = "UTF-8";
 51 
 52     // 二維碼寫碼器  
 53     private static MultiFormatWriter mutiWriter = new MultiFormatWriter();
 54 
 55     public static void main(String[] args) throws Exception {
 56         encode("https://hanyu.baidu.com/s?wd=%E7%99%BD%E6%97%A5%E6%A2%A6", 300, 300, "D:/cow.jpg",
 57                 "D:/cow二維碼.jpg");//"D:/jjsd.jpg"
 58         System.out.println("二維碼生成完畢!");
 59         System.out.println(decode("D:/cow二維碼.jpg"));
 60     }
 61 
 62     @SuppressWarnings({ "rawtypes", "unchecked" })
 63     public static String decode(File file) throws Exception {
 64         BufferedImage image;
 65         image = ImageIO.read(file);
 66         if (image == null) {
 67             return null;
 68         }
 69         BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
 70         BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
 71         Result result;
 72         Hashtable hints = new Hashtable();
 73         hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
 74         result = new MultiFormatReader().decode(bitmap, hints);
 75         String resultStr = result.getText();
 76         return resultStr;
 77     }
 78 
 79     public static String decode(String path) throws Exception {
 80         return decode(new File(path));
 81     }
 82 
 83     /** 
 84      *  
 85      * @param content 
 86      *            二維碼顯示的文本 
 87      * @param width 
 88      *            二維碼的寬度 
 89      * @param height 
 90      *            二維碼的高度 
 91      * @param srcImagePath 
 92      *            中間嵌套的圖片 
 93      * @param destImagePath 
 94      *            二維碼生成的地址 
 95      */
 96     public static void encode(String content, int width, int height, String srcImagePath,
 97             String destImagePath) {
 98         try {
 99             if (null != srcImagePath) {
100                 ImageIO.write(genBarcode(content, width, height, srcImagePath), IMAGE_FORMAT,
101                         new File(destImagePath));
102             } else {
103                 // 定義二維碼的參數
104                 HashMap<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
105                 // 定義字符集編碼格式
106                 hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
107                 // 糾錯的等級 L > M > Q > H 糾錯的能力越高可存儲的越少,一般使用M
108                 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
109                 // 設置圖片邊距
110                 hints.put(EncodeHintType.MARGIN, IMAGE_MARGIN);
111                 BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,
112                         width, height, hints);
113                 Path file = new File(destImagePath).toPath();
114                 MatrixToImageWriter.writeToPath(matrix, IMAGE_FORMAT, file);
115             }
116         } catch (IOException e) {
117             e.printStackTrace();
118         } catch (WriterException e) {
119             e.printStackTrace();
120         }
121     }
122 
123     /**
124      * 
125      * @param content
126      *             二維碼顯示的文本
127      * @param width
128      *             二維碼的寬度
129      * @param height
130      *             二維碼的高度
131      * @param srcImagePath
132      *             中間嵌套的路徑
133      * @param out
134      *             輸入到流中
135      */
136     public static void encode(String content, int width, int height, String srcImagePath,
137             OutputStream out) {
138         try {
139             if (null != srcImagePath) {
140                 ImageIO.write(genBarcode(content, width, height, srcImagePath), IMAGE_FORMAT, out);
141             } else {
142 
143                 // 定義二維碼的參數
144                 HashMap<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
145                 // 定義字符集編碼格式
146                 hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
147                 // 糾錯的等級 L > M > Q > H 糾錯的能力越高可存儲的越少,一般使用M
148                 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
149                 // 設置圖片邊距
150                 hints.put(EncodeHintType.MARGIN, IMAGE_MARGIN);
151                 BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,
152                         width, height, hints);
153                 MatrixToImageWriter.writeToStream(matrix, IMAGE_FORMAT, out);
154             }
155         } catch (IOException e) {
156             e.printStackTrace();
157         } catch (WriterException e) {
158             e.printStackTrace();
159         }
160     }
161 
162     /** 
163      * 得到BufferedImage 
164      *  
165      * @param content 
166      *            二維碼顯示的文本 
167      * @param width 
168      *            二維碼的寬度 
169      * @param height 
170      *            二維碼的高度 
171      * @param srcImagePath 
172      *            中間嵌套的圖片 
173      * @return 
174      * @throws WriterException 
175      * @throws IOException 
176      */
177     @SuppressWarnings({ "rawtypes", "unchecked" })
178     private static BufferedImage genBarcode(String content, int width, int height,
179             String srcImagePath) throws WriterException, IOException {
180         // 讀取源圖像  
181         BufferedImage scaleImage = scale(srcImagePath, IMAGE_WIDTH, IMAGE_HEIGHT, true);
182 
183         int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT];
184         for (int i = 0; i < scaleImage.getWidth(); i++) {
185             for (int j = 0; j < scaleImage.getHeight(); j++) {
186                 srcPixels[i][j] = scaleImage.getRGB(i, j);
187             }
188         }
189         Hashtable hint = new Hashtable();
190         hint.put(EncodeHintType.CHARACTER_SET, CHARSET);
191         hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
192         hint.put(EncodeHintType.MARGIN, IMAGE_MARGIN);
193         // 生成二維碼  
194         BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hint);
195 
196         // 二維矩陣轉為一維像素數組  
197         int halfW = matrix.getWidth() / 2;
198         int halfH = matrix.getHeight() / 2;
199         int[] pixels = new int[width * height];
200 
201         // System.out.println(matrix.getHeight());  
202         for (int y = 0; y < matrix.getHeight(); y++) {
203             for (int x = 0; x < matrix.getWidth(); x++) {
204                 // 讀取圖片  
205                 if (x > halfW - IMAGE_HALF_WIDTH && x < halfW + IMAGE_HALF_WIDTH
206                         && y > halfH - IMAGE_HALF_WIDTH && y < halfH + IMAGE_HALF_WIDTH) {
207                     pixels[y * width + x] = srcPixels[x - halfW + IMAGE_HALF_WIDTH][y - halfH
208                             + IMAGE_HALF_WIDTH];
209                 }
210                 // 在圖片四周形成邊框  
211                 else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
212                         && x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH
213                         && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH
214                         && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)
215                         || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH
216                                 && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
217                                 && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH
218                                 && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)
219                         || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
220                                 && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
221                                 && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH
222                                 && y < halfH - IMAGE_HALF_WIDTH + FRAME_WIDTH)
223                         || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
224                                 && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
225                                 && y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH
226                                 && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {
227                     pixels[y * width + x] = 0xfffffff;
228                 } else {
229                     // 此處可以修改二維碼的顏色,可以分別制定二維碼和背景的顏色;  
230                     pixels[y * width + x] = matrix.get(x, y) ? 0xff000000 : 0xfffffff;
231                 }
232             }
233         }
234 
235         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
236         image.getRaster().setDataElements(0, 0, width, height, pixels);
237 
238         return image;
239     }
240 
241     /** 
242      * 把傳入的原始圖像按高度和寬度進行縮放,生成符合要求的圖標 
243      *  
244      * @param srcImageFile 
245      *            源文件地址 
246      * @param height 
247      *            目標高度 
248      * @param width 
249      *            目標寬度 
250      * @param hasFiller 
251      *            比例不對時是否需要補白:true為補白; false為不補白; 
252      * @throws IOException 
253      */
254     private static BufferedImage scale(String srcImageFile, int height, int width,
255             boolean hasFiller) throws IOException {
256         double ratio = 0.0; // 縮放比例  
257 
258         //        URL url = new URL(srcImageFile);
259         //        HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
260         //        httpUrl.connect();
261 
262         File file = new File(srcImageFile);
263         BufferedImage srcImage = ImageIO.read(file);
264         //        BufferedImage srcImage = ImageIO.read(httpUrl.getInputStream());
265         Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
266         // 計算比例  
267         if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
268             if (srcImage.getHeight() > srcImage.getWidth()) {
269                 ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();
270             } else {
271                 ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();
272             }
273             AffineTransformOp op = new AffineTransformOp(
274                     AffineTransform.getScaleInstance(ratio, ratio), null);
275             destImage = op.filter(srcImage, null);
276         }
277         if (hasFiller) {// 補白  
278             BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
279             Graphics2D graphic = image.createGraphics();
280             graphic.setColor(Color.white);
281             graphic.fillRect(0, 0, width, height);
282             if (width == destImage.getWidth(null))
283                 graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2,
284                         destImage.getWidth(null), destImage.getHeight(null), Color.white, null);
285             else
286                 graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0,
287                         destImage.getWidth(null), destImage.getHeight(null), Color.white, null);
288             graphic.dispose();
289             destImage = image;
290         }
291         return (BufferedImage) destImage;
292     }
293 }

 

最終生成的二維碼:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM