import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable; import javax.imageio.ImageIO;
import org.zywx.appdo.omm.service.util.MutipartUploadFile;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class QRUtil {
/**
* 编码(将文本生成二维码)
*
* @param content
* 二维码中的内容
* @param width
* 二维码图片宽度
* @param height
* 二维码图片高度
* @param imagePath
* 二维码图片存放位置
* @return 图片地址
*/ public static String encode(String content, int width, int height,
String imagePath) {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 设置编码类型为utf-8
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 设置二维码纠错能力级别为H(最高)
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN, 0);//二维码边框 默认是4
BitMatrix byteMatrix = null;
try {
// 生成二维码
byteMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, width, height, hints);
File file = new File(imagePath);
MatrixToImageWriter.writeToFile(byteMatrix, "png", file);
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return imagePath;
}
/**
* 解码(读取二维码图片中的文本信息)
*
* @param imagePath
* 二维码图片路径
* @return 文本信息
*/
public static String decode(String imagePath) {
// 返回的文本信息
String content = "";
try {
// 创建图片文件
File file = new File(imagePath);
if (!file.exists()) {
return content;
}
BufferedImage image = null;
image = ImageIO.read(file);
if (null == image) {
return content;
}
// 解码
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Hashtable hints = new Hashtable();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result rs = new MultiFormatReader().decode(bitmap, hints);
content = rs.getText();
} catch (IOException e) {
e.printStackTrace();
} catch (ReaderException e) {
e.printStackTrace();
}
return content;
}
/**
* 图片打水印
*
* @param bgImage
* 背景图
* @param waterImg
* 水印图
* @param uniqueFlag
* 生成的新图片名称中的唯一标识,用来保证生成的图片名称不重复,如果为空或为null,将使用当前时间作为标识
* @return 新图片路径
*/
public static String addImageWater(String bgImage, String waterImg,
String uniqueFlag) {
int x = 0;
int y = 0;
String newImgPath = "";
if (null == uniqueFlag) {
uniqueFlag = new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date());
} else if (uniqueFlag.trim().length() < 1) {
uniqueFlag = new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date());
}
String fileName = "" ;
try {
File file = new File(bgImage);
fileName = file.getName();
Image image = ImageIO.read(file);
int width = image.getWidth(null);
int height = image.getHeight(null);
BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
Image waterImage = ImageIO.read(new File(waterImg)); // 水印文件
int width_water = waterImage.getWidth(null);
int height_water = waterImage.getHeight(null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
1));
int widthDiff = width - width_water;
int heightDiff = height - height_water;
x = widthDiff / 2;
y = heightDiff / 2;
g.drawImage(waterImage, x, y, width_water, height_water, null); // 水印文件结束
g.dispose();
if (bgImage.contains(fileName)) {
newImgPath = bgImage.replace(fileName, uniqueFlag + fileName);
fileName = uniqueFlag + fileName ;
}
File newImg = new File(newImgPath);
ImageIO.write(bufferedImage, "png", newImg);
File waterFile = new File(waterImg);
if (file.exists()) {
file.delete();
}
if (waterFile.exists()) {
waterFile.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
return fileName ;
}
/**
* 图片缩放
*
* @param filePath
* 图片路径
* @param height
* 缩放到高度
* @param width
* 缩放宽度
* @param fill
* 比例足时是否填白 true为填白,二维码是黑白色,这里调用时建议设为true
* @return 新图片路径
*/
public static String resizeImg(String filePath, int width, int height,
boolean fill) {
String newImgPath = "";
try {
double ratio = 0; // 缩放比例
File f = new File(filePath);
String fileName = f.getName();
BufferedImage bi = ImageIO.read(f);
Image itemp = bi.getScaledInstance(width, height,
BufferedImage.SCALE_SMOOTH);
if (height != 0 && width != 0) {
// 计算比例
if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
if (bi.getHeight() > bi.getWidth()) {
ratio = (new Integer(height)).doubleValue()
/ bi.getHeight();
} else {
ratio = (new Integer(width)).doubleValue()
/ bi.getWidth();
}
AffineTransformOp op = new AffineTransformOp(
AffineTransform.getScaleInstance(ratio, ratio),
null);
itemp = op.filter(bi, null);
}
}
if (fill) {
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
if (width == itemp.getWidth(null)) {
g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
itemp.getWidth(null), itemp.getHeight(null),
Color.white, null);
} else {
g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
itemp.getWidth(null), itemp.getHeight(null),
Color.white, null);
}
g.dispose();
itemp = image;
}
String now = new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date());
if (filePath.contains(fileName)) {
newImgPath = filePath.replace(fileName, now + fileName);
}
File newImg = new File(newImgPath);
ImageIO.write((BufferedImage) itemp, "png", newImg);
} catch (IOException e) {
e.printStackTrace();
}
return newImgPath;
}
/**
* 图片添加边框
*
* @param mainImgPath
* 要加边框的图片
* @param bgImgPath
* 背景图(实际上是将图片放在背景图上,只利用背景图的边框效果)
* @return 制作完成的图片路径
*/
public static String addWaterBorder(String mainImgPath, String bgImgPath) {
String borderImgPath = "";
try {
File f = new File(mainImgPath);
BufferedImage bi;
bi = ImageIO.read(f);
// 背景图长宽都比主图多4像素,这是因为我画的背景图的边框效果的大小正好是4像素,
// 主图周边比背景图少4像素正好能把背景图的边框效果完美显示出来
int width = bi.getWidth();
int height = bi.getHeight();
int bgWidth = width + 4;
int bgHeight = height + 4;
String now = new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date());
borderImgPath = QRUtil.addImageWater(
QRUtil.resizeImg(bgImgPath, bgHeight, bgWidth, true),
mainImgPath, now);
if (f.exists()) {
f.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
return borderImgPath;
}
/**
* 生成带有中间小图标的二维码
*
* @param imagePath 二维码保存地址
* @param content 二维码内容
* @param nginxUrl
* @param width
* @param height
* @return
*/
public static String createQR(String imagePath,String content,String nginxUrl,int width,int height){
//二维码图片中间的logo
String logoPath = imagePath + "logo.png";
imagePath += MutipartUploadFile.DEFAULT_FILE_NAME_GENERATOR.generate("jpg");
// 二维码存放地址
// 生成二维码,返回的是生成好的二维码图片的所在路径
String qrImgPath = QRUtil.encode(content, width, height, imagePath);
// 缩放水印图片,为保证二维码的读取正确,图片不超过二维码图片的五分之一,这里设为六分之一
String waterImgPath = QRUtil.resizeImg(logoPath, width / 6, height / 6, true);
// 生成带有图片的二维码,返回的是生成好的二维码图片的所在路径
String fileName = QRUtil.addImageWater(qrImgPath, waterImgPath, "a");
String filePath = nginxUrl + "appImages/" + fileName;
return filePath;
}
public static void main(String[] args) {
String imagePath ="e:/tmp/yqxbc/";
String content = "http://www.zftb.cn";
String nginxUrl= "http://192.168.1.2:8888/" ;
int width = 300;
int height = 300;
System.out.println(createQR(imagePath,content,nginxUrl,width,height));
}
}