java生成二维码,图片处理

前段时间搞了一个二维码生成,搞定之后将代码分享出来,直接上代码



import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;

import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.FileUtils;

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 sun.font.FontDesignMetrics;

/**
 * 
 * 二维码工具类
 * 
* * @author naveu * @date 2018年7月19日 下午3:08:36 */ @SuppressWarnings("restriction") public class QRCodeUtils2 { private QRCodeUtils2() {} private static final int BLACK = 0xFF000000; private static final int WHITE = 0xFFFFFFFF; /** *
     * 生成二维码图片对象
     * 
* @author naveu * @date 2018年8月6日 下午12:44:27 * @param qrUrl 二维码链接 * @param qrLen 二维码边长,正方形 * @return * @throws WriterException */ public static BufferedImage getQRImg(String qrUrl, int qrLen) throws WriterException { Hashtable hints = new Hashtable<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); hints.put(EncodeHintType.MARGIN, 1); BitMatrix matrix = new MultiFormatWriter().encode(qrUrl, BarcodeFormat.QR_CODE, qrLen, qrLen, hints); BufferedImage image = new BufferedImage(qrLen, qrLen, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < qrLen; x++) { for (int y = 0; y < qrLen; y++) { image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); } } return image; } /** *
     * 获取字体宽度
     * 
* @author naveu * @date 2018年8月6日 下午12:44:36 * @param font 字体 * @param text 字符内容 * @return */ public static int getFontWidth(Font font, String text) { FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); int width = 0; for (int i = 0; i < text.length(); i++) { width += metrics.charWidth(text.charAt(i)); } return width; } /** *
     * 生成文字图片对象
     * 
* @author naveu * @date 2018年8月6日 下午12:44:39 * @param text 文字内容 * @param textFont 字体 * @param width 图片宽度,小于0将使用字体宽度 * @param height 图片高度,小于0将使用字体高度 * @param bgColor 图片背景色 * @param fontColor 字体色 * @param fontX 字体x坐标 * @param fontY 字体y坐标 * @return * @throws Exception */ public static BufferedImage getTextImg(String text, Font textFont, Integer width, Integer height, Color bgColor, Color fontColor, Integer fontX, Integer fontY) throws Exception { FontDesignMetrics metrics = FontDesignMetrics.getMetrics(textFont); if (width < 0) { width = getFontWidth(textFont, text);// 计算图片的宽 } if (height < 0) { height = metrics.getHeight();// 计算图片的高 } // 创建一个BufferedImage对象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); graphics.setColor(bgColor); // 先用背景色填充整张图片,也就是背景 graphics.fillRect(0, 0, width, height);// 画出矩形区域,以便于在矩形区域内写入文字 graphics.setColor(fontColor);// 再换成字体色,以便于写入文字 graphics.setFont(textFont);// 设置画笔字体 graphics.drawString(text, fontX, fontY + metrics.getAscent());// 画出一行字符串 graphics.dispose(); return image; } /** *
     * 将两张图片叠加成一张新的图片
     * 一般情况上层图片小,下层图片大
     * 
* @author naveu * @date 2018年8月6日 下午12:44:43 * @param image 下层图片 * @param img 上层图片 * @param x 上层图片叠加位置x坐标,小于0将放于中间位置 * @param y 上层图片叠加位置y坐标,小于0将放于中间位置 * @return * @throws Exception */ public static BufferedImage imgOnImage(BufferedImage image, BufferedImage img, Integer x, Integer y) throws Exception { // 内图的宽高 int innerWidth = img.getWidth(); int innerHeigh = img.getHeight(); if (y < 0) { y = (image.getHeight() - innerHeigh) / 2; } if (x < 0) { x = (image.getWidth() - innerWidth) / 2; } // 开始绘制图片前两个 Graphics2D g2 = image.createGraphics(); g2.drawImage(img, x, y, innerWidth, innerHeigh, null); g2.dispose(); // 执行刷出返回合成的图片 image.flush(); return image; } /** *
     * 图片对象写入文件
     * 
* @author naveu * @date 2018年8月6日 下午12:44:46 * @param image 图片对象 * @param imgFile 图片文件 * @throws IOException * @throws WriterException */ public static void imgToFile(BufferedImage image, File imgFile) throws IOException, WriterException { // 文件类型 final String formatName = imgFile.getName().substring(imgFile.getName().lastIndexOf(".") + 1); ImageIO.write(image, formatName, imgFile); } /** *
     * 图片对象写入文件,可设置分辩率
     * 
* @author naveu * @date 2018年8月8日 下午1:36:38 * @param image 图片对象 * @param imgFile 图片文件 * @param dpi 分辩率dpi值 * @throws IOException */ public static void imgToFile(BufferedImage image, File imgFile, Integer dpi) throws IOException { imgFile.delete(); // 文件类型 final String formatName = imgFile.getName().substring(imgFile.getName().lastIndexOf(".") + 1); // 粗略计算发现,设置新生成图片的dpi值在这里要除以25.4,暂不知道是为什么,不明白分辩率是如何计算的 final String dotsPerMilli = new DecimalFormat("#.00").format(dpi / 25.4); for (Iterator iw = ImageIO.getImageWritersByFormatName(formatName); iw.hasNext();) { ImageWriter writer = iw.next(); ImageWriteParam writeParam = writer.getDefaultWriteParam(); ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam); if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) { continue; } /******************设置分辩率begin************************/ // 水平分辩率 IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize"); horiz.setAttribute("value", dotsPerMilli); // 垂直分辩率 IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize"); vert.setAttribute("value", dotsPerMilli); IIOMetadataNode dim = new IIOMetadataNode("Dimension"); dim.appendChild(horiz); dim.appendChild(vert); IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0"); root.appendChild(dim); metadata.mergeTree("javax_imageio_1.0", root); /******************设置分辩率end************************/ // 数据写入文件 final ImageOutputStream stream = ImageIO.createImageOutputStream(imgFile); try { writer.setOutput(stream); writer.write(metadata, new IIOImage(image, null, metadata), writeParam); } finally { stream.close(); } break; } } /** *
     * 图片对象写入输出流
     * 
* @author naveu * @date 2018年8月6日 下午12:44:50 * @param image 图片对象 * @param imgType 图片类型 PNG JPG等 * @param stream 输出流 * @throws IOException * @throws WriterException */ public static void imgToStream(BufferedImage image, String imgType, OutputStream stream) throws IOException, WriterException { ImageIO.write(image, imgType, stream); } /** *
     * 获取图片指定坐标处背景色
     * 
* @author naveu * @date 2018年8月6日 下午12:44:54 * @param image 图片对象 * @param x x坐标 * @param y y坐标 * @return */ public static Color getImgRGBColor(BufferedImage image, int x, int y) { int green = 0, red = 0, blue = 0; Object data = image.getRaster().getDataElements(x, y, null);// 获取像素点 // ColorModel是一个用来将图片某点的rgb值分别取出的类,包括取出alpha值 red = image.getColorModel().getRed(data); green = image.getColorModel().getGreen(data); blue = image.getColorModel().getBlue(data); return new Color(red, green, blue); } /** *
     * 文件压缩zip
     * 
* @author naveu * @date 2018年8月6日 下午2:12:18 * @param files * @param zipFile */ public static void zipCompress(List files, File zipFile) { ZipArchiveOutputStream zos = null; FileOutputStream zipFos = null; ArchiveOutputStream archOut = null; try { zipFos = new FileOutputStream(zipFile); archOut = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, zipFos); if (archOut instanceof ZipArchiveOutputStream) { zos = (ZipArchiveOutputStream) archOut; for (int i = 0; i < files.size(); i++) { zos.putArchiveEntry(new ZipArchiveEntry(files.get(i), files.get(i).getName())); zos.write(FileUtils.readFileToByteArray(files.get(i))); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != zos) { zos.flush(); zos.closeArchiveEntry(); zos.close(); } if (null != archOut) { archOut.close(); } if (null != zipFos) { zipFos.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** *
     * Image转BufferedImage
     * 
* @author naveu * @date 2018年8月8日 下午1:37:41 * @param image * @param type * @return */ public static BufferedImage toBufferedImage(Image image, int type) { int w = image.getWidth(null); int h = image.getHeight(null); BufferedImage result = new BufferedImage(w, h, type); Graphics2D g = result.createGraphics(); g.drawImage(image, 0, 0, null); g.dispose(); return result; } /** *
     * 测试生成二维码方法
     * 
* @author naveu * @date 2018年8月9日 下午5:01:25 * @param code * @return * @throws Exception */ private static File testQr(String code) throws Exception { // 获取模板图片对象 BufferedImage image = ImageIO.read(new File("e:\\qr\\srcImg.png")); // 生成二维码图片对象 BufferedImage qrImg = getQRImg("http://www.baidu.com", 130); // 获取模板一个坐标点的背景色对象 Color bgColor = getImgRGBColor(image, 10, 10); // 生成编号号图片对象 BufferedImage codeImg = getTextImg(code, new Font("Arial Bold", Font.BOLD, 120), 150, 150, bgColor, Color.WHITE, 0, 0); // 将二维码图片合成到模板图片上 image = imgOnImage(image, qrImg, 245, -1); // 将编号号图片合成到模板图片上 image = imgOnImage(image, codeImg, 30, -1); // 创建新的图片文件 File newImg = new File("e:\\qr\\testQr\\" + code + ".png"); if (!newImg.getParentFile().exists()) { newImg.getParentFile().mkdirs(); } if (!newImg.exists()) { newImg.createNewFile(); } // 将合成的图片写入图片文件,保存本地文件 imgToFile(image, newImg, 150); return newImg; } public static void main(String[] args) throws Exception { // 编号号 String[] codes = {"01", "02", "03", "04"}; // 生成的所有图片 List qrFiles = new ArrayList<>(); for (int i = 0; i < codes.length; i++) { qrFiles.add(testQr(codes[i])); } if (!qrFiles.isEmpty()) { // 图片文件压缩包 File zipFile = new File("e:\\qr\\testCodes.zip"); if (!zipFile.getParentFile().exists()) { zipFile.getParentFile().mkdirs(); } if (!zipFile.exists()) { zipFile.createNewFile(); } // 压缩图片文件 zipCompress(qrFiles, zipFile); // 删除生成的所有图片文件夹 File dir = qrFiles.get(0).getParentFile(); if (dir.exists() && dir.isDirectory()) { FileUtils.deleteDirectory(dir); } } } }

模板图片java生成二维码,图片处理_第1张图片

生成结果图片java生成二维码,图片处理_第2张图片

 

你可能感兴趣的:(java)