1、多個圖檔合成
2、生成不帶logo的二維碼
3、讀取圖檔二維碼資訊
4、生成帶logo的二維碼
5、圖檔壓縮
6、文字水印到圖檔
7、圖檔水印到圖檔
9、解決圖檔紅色問題 ,JDK中提供的Image
package com.hlj.util.QRcode;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
/**
* 作者 :HealerJean
* 日期 :2018/10/29 下午4:31.
* 類描述:
*/
public class QrCodeUtils {
/**
*
* 1、 輸出圖檔到本地目錄
* @param buffImg 圖檔
* @param savePath 本地目錄的路徑
*/
public static void saveImageToLocalDir(BufferedImage buffImg, String savePath) {
try {
ImageIO.write(buffImg, "jpg", new File(savePath));
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
*
* 2、 方法描述: 多個圖檔合成
* exImage 底圖
* innerImage 嵌入的圖檔
* x 坐标x
* y 坐标y
* innerImageWedith 嵌入圖檔的長度
* innerImageHeight 嵌入圖檔的寬度
*/
public static BufferedImage imageAndImages(BufferedImage exImage, BufferedImage innerImage, int x, int y, int innerImageWedith, int innerImageHeight, float alpha) throws IOException {
Graphics2D g2d = exImage.createGraphics();
// 在圖形和圖像中實作混合和透明效果
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 繪制
g2d.drawImage(innerImage, x, y, innerImageWedith, innerImageHeight, null);
g2d.dispose();// 釋放圖形上下文使用的系統資源
return exImage;
}
/**
* 2、測試 多個圖檔合成
*/
@Test
public void testimageAndImages(){
String sourceFilePath = "/Users/healerjean/Desktop/origin.jpeg";
String innerImageFilePath = "/Users/healerjean/Desktop/img.jpeg";
// 建構疊加層
BufferedImage buffImg = null;
try {
buffImg = imageAndImages(ImageIO.read(new File(sourceFilePath)), ImageIO.read(new File(innerImageFilePath)),238, 588,210 ,208, 1.0f);
} catch (IOException e) {
e.printStackTrace();
}
// 輸出水印圖檔
String saveFilePath = "/Users/healerjean/Desktop/new.png";
saveImageToLocalDir(buffImg, saveFilePath);
}
/**
* 3、不帶logo的二維碼
*
* @param text 二維碼内容
* @param width 二維碼寬度
* @param height 長度
* @param whiteSize 白邊大小
* @return
*/
public static BufferedImage writeQRImg(String text,int width,int height,int whiteSize){
// 配置參數
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 字元編碼
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 容錯級别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 設定空白邊距的寬度
hints.put(EncodeHintType.MARGIN, whiteSize); // 預設是4
// 1、生成二維碼
BitMatrix bitMatrix = null;
try {
bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
} catch (WriterException e) {
e.printStackTrace();
}
// 2、擷取二維碼寬高
int codeWidth = bitMatrix.getWidth();
int codeHeight = bitMatrix.getHeight();
// 3、将二維碼放入緩沖流
BufferedImage image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < codeWidth; i++) {
for (int j = 0; j < codeHeight; j++) {
// 4、循環将二維碼内容定入圖檔
//判斷 BitMatrix 是否存在像素 二維碼填充顔色 黑色 0XFF000000 白色 :0xFF是補碼 0XFFFFFFFF
image.setRGB(i, j, bitMatrix.get(i, j) ? 0XFF000000 : 0XFFFFFFFF);
}
}
return image ;
}
/**
* 3、測試 不帶logo的二維碼
* @throws Exception
*/
@Test
public void testWriteQRImg(){
String text = "http://blog.healerjean.top";
BufferedImage noLogoImage = writeQRImg(text,200,200, 4 );
//存儲到本地
String saveFilePath = "/Users/healerjean/Desktop/new.png";
saveImageToLocalDir(noLogoImage, saveFilePath);
}
/**
* 4、 讀取二維碼的檔案裡面的資訊
*/
public static String readQRImg(BufferedImage image) throws Exception {
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
// 字元編碼
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 對圖像進行解碼
return result.getText();
}
/**
* 4、測試 讀取二維碼資訊
* @throws Exception
*/
@Test
public void testReadQRImg() throws Exception{
//讀取二維碼資訊
String filePath = "/Users/healerjean/Desktop/new.png";
BufferedImage image = ImageIO.read(new File(filePath));
String info =readQRImg(image);
System.out.println(info);
}
/**
* 5、 生成帶logo的二維碼
*
*
* @param text 二維碼内容
* @param text 二維碼内容
* @param width 二維碼寬度
* @param height 長度
* @param whiteSize 白邊大小
* @param logo LOGO圖檔
* @return
* @throws Exception
*/
public static BufferedImage createLogoQRImg(String text,int width,int height, int whiteSize,BufferedImage logo) throws Exception {
// 配置參數
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 字元編碼
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 容錯級别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 設定空白邊距的寬度
hints.put(EncodeHintType.MARGIN, whiteSize); // 預設是4
// 1、生成二維碼
BitMatrix bitMatrix = null;
try {
bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
} catch (WriterException e) {
e.printStackTrace();
}
// 2、擷取二維碼寬高
int codeWidth = bitMatrix.getWidth();
int codeHeight = bitMatrix.getHeight();
// 3、将二維碼放入緩沖流
BufferedImage image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < codeWidth; i++) {
for (int j = 0; j < codeHeight; j++) {
// 4、循環将二維碼内容定入圖檔
//判斷 BitMatrix 是否存在像素 二維碼填充顔色 黑色 0XFF000000 白色 :0xFF是補碼 0XFFFFFFFF
image.setRGB(i, j, bitMatrix.get(i, j) ? 0XFF000000 : 0XFFFFFFFF);
}
}
//在原來基礎上,再添加一個圖檔
Graphics2D g = image.createGraphics();
int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ?
(image.getWidth() * 2 / 10) : logo.getWidth(null);
int heightLogo = logo.getHeight(null) > image.getHeight() * 2 / 10 ?
(image.getHeight() * 2 / 10) : logo.getHeight(null);
//設定在圖檔中間
int x = (image.getWidth() - widthLogo) / 2;
int y = (image.getHeight() - heightLogo) / 2;
// 開始繪制圖檔
g.drawImage(logo, x, y, widthLogo, heightLogo, null);
//繪制圓角矩形
g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
//邊框寬度
g.setStroke(new BasicStroke(2));
//邊框顔色
g.setColor(Color.WHITE);
g.drawRect(x, y, widthLogo, heightLogo);
g.dispose();
logo.flush();
image.flush();
return image;
}
/**
* 5、測試 帶logo的二維碼
* @throws Exception
*/
@Test
public void testWriteQRImgWithLogo() throws Exception{
String text = "http://blog.healerjean.top";
String logoPath = "/Users/healerjean/Desktop/logo.png";
BufferedImage logo = ImageIO.read(new File(logoPath));
BufferedImage logoImage = createLogoQRImg(text,200,200, 1 ,logo);
//存儲到本地
String saveFilePath = "/Users/healerjean/Desktop/new.png";
saveImageToLocalDir(logoImage, saveFilePath);
}
/**
* 6/ 指定圖檔寬度和高度和壓縮比例對圖檔進行壓縮
* @param widthdist 壓縮後圖檔的寬度
* @param heightdist 壓縮後圖檔的高度
* @param rate 壓縮的比例 ,可以設定為null
*/
public static BufferedImage reduceImg(BufferedImage bufferedImage, int widthdist, int heightdist, Float rate) {
try {
// 如果比例不為空則說明是按比例壓縮
if (rate != null && rate > 0) {
//獲得源圖檔的寬高存入數組中
int results[] = { 0, 0 };
results[0] =bufferedImage.getWidth(null); // 得到源圖檔寬
results[1] =bufferedImage.getHeight(null);// 得到源圖檔高
if (results == null || results[0] == 0 || results[1] == 0) {
return null;
} else {
//按比例縮放或擴大圖檔大小,将浮點型轉為整型
widthdist = (int) (results[0] * rate);
heightdist = (int) (results[1] * rate);
}
}
// 開始讀取檔案并進行壓縮
Image src = (Image) bufferedImage;
// 構造一個類型為預定義圖像類型之一的 BufferedImage
BufferedImage tag = new BufferedImage((int) widthdist, (int) heightdist, BufferedImage.TYPE_INT_RGB);
//繪制圖像 getScaledInstance表示建立此圖像的縮放版本,傳回一個新的縮放版本Image,按指定的width,height呈現圖像
//Image.SCALE_SMOOTH,選擇圖像平滑度比縮放速度具有更高優先級的圖像縮放算法。
tag.getGraphics().drawImage(src.getScaledInstance(widthdist, heightdist, Image.SCALE_SMOOTH), 0, 0, null);
return tag;
} catch (Exception ef) {
ef.printStackTrace();
}
return null;
}
/**
* 6 測試
* @throws IOException
*/
@Test
public void testReduceImg() throws IOException {
String reducePath = "/Users/healerjean/Desktop/reduce.png";
BufferedImage originImage = ImageIO.read(new File(reducePath));
BufferedImage reduceImg = reduceImg(originImage,200,200, null );
//存儲到本地
String saveFilePath = "/Users/healerjean/Desktop/new.png";
saveImageToLocalDir(reduceImg, saveFilePath);
}
/**
* 7、 添加文字水印
* @param image 需要加水印的檔案
* @param waterText 水印文本
* @param moreMark 是否是多個水印 true多個水印 /false 或不寫,一個水印
* @return
*/
public static BufferedImage textWaterMark(BufferedImage image,String waterText, boolean... moreMark) {
//字型樣式
int FONT_STYLE = Font.BOLD;
//字型大小
int FONT_SIZE = 50;
//字型顔色
Color FONT_COLOR = Color.black;
//字型顔色
String FONT_NAME = "微軟雅黑";
//透明度
float ALPHA = 0.3F;
//多圖的情況下,水印的間距
Integer MORE_MARK_DISTANCE = 100;
//計算原始圖檔寬度長度
int width = image.getWidth();
int height = image.getHeight();
//建立圖檔緩存對象
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//建立java繪圖工具對象
Graphics2D graphics2d = bufferedImage.createGraphics();
//參數主要是,原圖,坐标,寬高
graphics2d.drawImage(image, 0, 0, width, height, null);
//使用繪圖工具将水印繪制到圖檔上
//計算文字水印寬高值
int waterWidth = FONT_SIZE*getTextLength(waterText);
int waterHeight = FONT_SIZE;
//水印透明設定
graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
graphics2d.setColor(FONT_COLOR);
if(moreMark!= null && moreMark.length >0 && moreMark[0]){
//設定旋轉 , 後面兩個參數表示的是圍繞那個坐标
graphics2d.rotate(Math.toRadians(-30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);
int x = -width/2;
int y = -height/2;
while(x < width*1.5){
y = -height/2;
while(y < height*1.5){
graphics2d.drawString(waterText, x, y);
//水印的間距
y+=waterHeight+MORE_MARK_DISTANCE;
}
x+=waterWidth+MORE_MARK_DISTANCE;
}
}else{
graphics2d.drawString(waterText, width-waterWidth, height);
}
//寫圖檔
graphics2d.dispose();
return bufferedImage;
}
/**
* 計算水印文本長度
*
* 中文長度即文本長度 2、英文長度為文本長度二分之一
* @param text
* @return
*/
private static int getTextLength(String text){
//水印文字長度
int length = text.length();
for (int i = 0; i < text.length(); i++) {
String s =String.valueOf(text.charAt(i));
if (s.getBytes().length>1) {
length++;
}
}
length = length%2==0?length/2:length/2+1;
return length;
}
@Test
public void testTextWaterMark() throws IOException {
String originPath = "/Users/healerjean/Desktop/reduce.png";
BufferedImage originImage = ImageIO.read(new File(originPath));
BufferedImage newImage = textWaterMark(originImage,"healerjean",true);
//存儲到本地
String saveFilePath = "/Users/healerjean/Desktop/new.png";
saveImageToLocalDir(newImage, saveFilePath);
}
/**
* 8、 添加圖檔水印
* @param srcFile 需要家水印的檔案路徑
* @return
*/
public static BufferedImage imageWaterMark(BufferedImage image,BufferedImage imageLogo, boolean... moreMark) {
//字型樣式
int FONT_STYLE = Font.BOLD;
//字型大小
int FONT_SIZE = 50;
//字型顔色
Color FONT_COLOR = Color.black;
//字型顔色
String FONT_NAME = "微軟雅黑";
//透明度
float ALPHA = 0.3F;
//多圖的情況下,水印的間距
Integer MORE_MARK_DISTANCE = 100;
int X = 636;
int Y = 763;
//計算原始圖檔寬度長度
int width = image.getWidth(null);
int height = image.getHeight(null);
//建立圖檔緩存對象
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//建立java繪圖工具對象
Graphics2D graphics2d = bufferedImage.createGraphics();
//參數主要是,原圖,坐标,寬高
graphics2d.drawImage(image, 0, 0, width, height, null);
graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
graphics2d.setColor(FONT_COLOR);
//水印圖檔路徑
int widthLogo = imageLogo.getWidth(null);
int heightLogo = imageLogo.getHeight(null);
int widthDiff = width-widthLogo;
int heightDiff = height-heightLogo;
//水印坐标設定
if (X > widthDiff) {
X = widthDiff;
}
if (Y > heightDiff) {
Y = heightDiff;
}
//水印透明設定
graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
if(moreMark!= null && moreMark.length >0 && moreMark[0]){
graphics2d.rotate(Math.toRadians(-30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);
int x = -width/2;
int y = -height/2;
while(x < width*1.5){
y = -height/2;
while(y < height*1.5){
graphics2d.drawImage(imageLogo, x, y, null);
y+=heightLogo+MORE_MARK_DISTANCE;
}
x+=widthLogo+MORE_MARK_DISTANCE;
}
}else{
graphics2d.drawImage(imageLogo, X, Y, null);
}
graphics2d.dispose();
return bufferedImage;
}
@Test
public void testImageWaterMark() throws IOException {
String originPath = "/Users/healerjean/Desktop/reduce.png";
BufferedImage originImage = ImageIO.read(new File(originPath));
String logoPath = "/Users/healerjean/Desktop/origin.jpeg";
BufferedImage logoImage = ImageIO.read(new File(logoPath));
BufferedImage newImage = imageWaterMark(originImage,logoImage,true);
//存儲到本地
String saveFilePath = "/Users/healerjean/Desktop/new.png";
saveImageToLocalDir(newImage, saveFilePath);
}
/**
* 9、解決圖檔紅色問題 ,JDK中提供的Image
//如果是file
Image src=Toolkit.getDefaultToolkit().getImage(file.getPath());
如果是url
URL url = new URL(wechat_erweimaTmail);
java.awt.Image imageTookittitle = Toolkit.getDefaultToolkit().createImage(url);
BufferedImage titleLab = ImageUtils.toBufferedImage(imageTookittitle);
* @param image
* @return
*/
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
try {
int transparency = Transparency.OPAQUE;
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null),
image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
bimage = new BufferedImage(image.getWidth(null),
image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
}