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 }

 

最终生成的二维码:

 

posted on 2021-02-10 11:33  IT-风  阅读(930)  评论(0编辑  收藏  举报

导航