add methods

This commit is contained in:
Looly 2020-05-19 17:17:17 +08:00
parent a25b2afeef
commit 4b53701670
5 changed files with 170 additions and 93 deletions

View File

@ -3,13 +3,15 @@
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
## 5.3.6 (2020-05-17) ## 5.3.6 (2020-05-19)
### 新特性 ### 新特性
* 【core 】 NumberConverter Long类型增加日期转换pr#872@Github * 【core 】 NumberConverter Long类型增加日期转换pr#872@Github
* 【all 】 StrUtil and SymmetricCrypto注释修正pr#873@Github * 【all 】 StrUtil and SymmetricCrypto注释修正pr#873@Github
* 【core 】 CsvReader支持返回Beanissue#869@Github * 【core 】 CsvReader支持返回Beanissue#869@Github
* 【core 】 Snowflake循环等待下一个时间时避免长时间循环加入对时钟倒退的判断pr#874@Github * 【core 】 Snowflake循环等待下一个时间时避免长时间循环加入对时钟倒退的判断pr#874@Github
* 【extra 】 新增 QRCode base64 编码形式返回pr#878@Github
* 【core 】 ImgUtil增加toBase64DateUriURLUtil增加getDataUri方法
### Bug修复 ### Bug修复

View File

@ -13,6 +13,7 @@ import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import javax.imageio.IIOImage; import javax.imageio.IIOImage;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@ -1261,6 +1262,20 @@ public class ImgUtil {
return IoUtil.toStream(toBytes(image, imageType)); return IoUtil.toStream(toBytes(image, imageType));
} }
/**
* 将图片对象转换为Base64的Data URI形式格式为data:image/[imageType];base64,[data]
*
* @param image 图片对象
* @param imageType 图片类型
* @return Base64的字符串表现形式
* @since 5.3.6
*/
public static String toBase64DateUri(Image image, String imageType) {
return URLUtil.getDataUri(
"image/" + imageType, "base64",
toBase64(image, imageType));
}
/** /**
* 将图片对象转换为Base64形式 * 将图片对象转换为Base64形式
* *

View File

@ -28,7 +28,16 @@ import java.util.Map;
import java.util.jar.JarFile; import java.util.jar.JarFile;
/** /**
* 统一资源定位符相关工具类 * URLUniform Resource Locator统一资源定位符相关工具类
*
* <p>
* 统一资源定位符描述了一台特定服务器上某资源的特定位置
* </p>
* URL组成
* <pre>
* 协议://主机名[:端口]/ 路径/[:参数] [?查询]#Fragment
* protocol :// hostname[:port] / path / [:parameters][?query]#fragment
* </pre>
* *
* @author xiaoleilu * @author xiaoleilu
*/ */
@ -749,8 +758,8 @@ public class URLUtil {
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
* @since 5.3.4 * @since 5.3.4
*/ */
public static long getContentLength(URL url) throws IORuntimeException{ public static long getContentLength(URL url) throws IORuntimeException {
if(null == url){ if (null == url) {
return -1; return -1;
} }
@ -762,8 +771,61 @@ public class URLUtil {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} finally { } finally {
if (conn instanceof HttpURLConnection) { if (conn instanceof HttpURLConnection) {
((HttpURLConnection)conn).disconnect(); ((HttpURLConnection) conn).disconnect();
} }
} }
} }
/**
* Data URI Scheme封装data URI scheme 允许我们使用内联inline-code的方式在网页中包含数据<br>
* 目的是将一些小的数据直接嵌入到网页中从而不用再从外部文件载入常用于将图片嵌入网页
*
* <p>
* Data URI的格式规范
* <pre>
* data:[<mime type>][;charset=<charset>][;<encoding>],<encoded data>
* </pre>
*
* @param mimeType 可选项null表示无数据类型image/pngtext/plain等
* @param encoding 数据编码方式US-ASCIIBASE64等
* @param data 编码后的数据
* @return Data URI字符串
* @since 5.3.6
*/
public static String getDataUri(String mimeType, String encoding, String data){
return getDataUri(mimeType, null, encoding, data);
}
/**
* Data URI Scheme封装data URI scheme 允许我们使用内联inline-code的方式在网页中包含数据<br>
* 目的是将一些小的数据直接嵌入到网页中从而不用再从外部文件载入常用于将图片嵌入网页
*
* <p>
* Data URI的格式规范
* <pre>
* data:[<mime type>][;charset=<charset>][;<encoding>],<encoded data>
* </pre>
*
* @param mimeType 可选项null表示无数据类型image/pngtext/plain等
* @param charset 可选项null表示无源文本的字符集编码方式
* @param encoding 数据编码方式US-ASCIIBASE64等
* @param data 编码后的数据
* @return Data URI字符串
* @since 5.3.6
*/
public static String getDataUri(String mimeType, Charset charset, String encoding, String data){
final StringBuilder builder = StrUtil.builder("data:");
if(StrUtil.isNotBlank(mimeType)){
builder.append(mimeType);
}
if(null != charset){
builder.append(";charset=").append(charset.name());
}
if(StrUtil.isNotBlank(encoding)){
builder.append(';').append(encoding);
}
builder.append(',').append(data);
return builder.toString();
}
} }

View File

@ -1,5 +1,6 @@
package cn.hutool.extra.qrcode; package cn.hutool.extra.qrcode;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.Img; import cn.hutool.core.img.Img;
import cn.hutool.core.img.ImgUtil; import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CharsetUtil;
@ -19,24 +20,17 @@ import com.google.zxing.common.HybridBinarizer;
import java.awt.Image; import java.awt.Image;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import javax.imageio.ImageIO;
/** /**
* 基于Zxing的二维码工具类 * 基于Zxing的二维码工具类
* *
* @author looly * @author looly
* @since 4.0.2 * @since 4.0.2
*
*/ */
public class QrCodeUtil { public class QrCodeUtil {
@ -50,13 +44,7 @@ public class QrCodeUtil {
* @return 图片 Base64 编码字符串 * @return 图片 Base64 编码字符串
*/ */
public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, String logoBase64) { public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, String logoBase64) {
byte[] decode; return generateAsBase64(content, qrConfig, imageType, Base64.decode(logoBase64));
try {
decode = Base64.getDecoder().decode(logoBase64);
} catch (Exception e) {
throw new QrCodeException(e);
}
return generateAsBase64(content, qrConfig, imageType, decode);
} }
/** /**
@ -69,36 +57,46 @@ public class QrCodeUtil {
* @return 图片 Base64 编码字符串 * @return 图片 Base64 编码字符串
*/ */
public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, byte[] logo) { public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, byte[] logo) {
BufferedImage img; return generateAsBase64(content, qrConfig, imageType, ImgUtil.toImage(logo));
try { }
img = ImageIO.read(new ByteArrayInputStream(logo));
} catch (IOException e) { /**
throw new QrCodeException(e); * 生成代 logo 图片的 Base64 编码格式的二维码 String 形式表示
} *
qrConfig.setImg(img); * @param content 内容
* @param qrConfig 二维码配置包括长边距颜色等
* @param imageType 图片类型图片扩展名{@link ImgUtil}
* @param logo logo 图片的byte[]
* @return 图片 Base64 编码字符串
*/
public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, Image logo) {
qrConfig.setImg(logo);
return generateAsBase64(content, qrConfig, imageType); return generateAsBase64(content, qrConfig, imageType);
} }
/** /**
* 生成 Base64 编码格式的二维码 String 形式表示 * 生成 Base64 编码格式的二维码 String 形式表示
* *
* <p>
* 输出格式为: data:image/[type];base64,[data]
* </p>
*
* @param content 内容 * @param content 内容
* @param qrConfig 二维码配置包括长边距颜色等 * @param qrConfig 二维码配置包括长边距颜色等
* @param imageType 图片类型图片扩展名{@link ImgUtil} * @param imageType 图片类型图片扩展名{@link ImgUtil}
* @return 图片 Base64 编码字符串 * @return 图片 Base64 编码字符串
*/ */
public static String generateAsBase64(String content, QrConfig qrConfig, String imageType) { public static String generateAsBase64(String content, QrConfig qrConfig, String imageType) {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); final BufferedImage img = generate(content, qrConfig);
generate(content, qrConfig, imageType, bos); return ImgUtil.toBase64DateUri(img, imageType);
byte[] encode = Base64.getEncoder().encode(bos.toByteArray());
return MessageFormat.format("data:image/{0};base64,{1}", imageType, new String(encode));
} }
/** /**
* 生成PNG格式的二维码图片以byte[]形式表示 * 生成PNG格式的二维码图片以byte[]形式表示
* *
* @param content 内容 * @param content 内容
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @return 图片的byte[] * @return 图片的byte[]
* @since 4.0.10 * @since 4.0.10
*/ */
@ -112,7 +110,7 @@ public class QrCodeUtil {
* 生成PNG格式的二维码图片以byte[]形式表示 * 生成PNG格式的二维码图片以byte[]形式表示
* *
* @param content 内容 * @param content 内容
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @return 图片的byte[] * @return 图片的byte[]
* @since 4.1.2 * @since 4.1.2
*/ */
@ -125,9 +123,9 @@ public class QrCodeUtil {
/** /**
* 生成二维码到文件二维码图片格式取决于文件的扩展名 * 生成二维码到文件二维码图片格式取决于文件的扩展名
* *
* @param content 文本内容 * @param content 文本内容
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @param targetFile 目标文件扩展名决定输出格式 * @param targetFile 目标文件扩展名决定输出格式
* @return 目标文件 * @return 目标文件
*/ */
@ -140,8 +138,8 @@ public class QrCodeUtil {
/** /**
* 生成二维码到文件二维码图片格式取决于文件的扩展名 * 生成二维码到文件二维码图片格式取决于文件的扩展名
* *
* @param content 文本内容 * @param content 文本内容
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @param targetFile 目标文件扩展名决定输出格式 * @param targetFile 目标文件扩展名决定输出格式
* @return 目标文件 * @return 目标文件
* @since 4.1.2 * @since 4.1.2
@ -155,11 +153,11 @@ public class QrCodeUtil {
/** /**
* 生成二维码到输出流 * 生成二维码到输出流
* *
* @param content 文本内容 * @param content 文本内容
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @param imageType 图片类型图片扩展名{@link ImgUtil} * @param imageType 图片类型图片扩展名{@link ImgUtil}
* @param out 目标流 * @param out 目标流
*/ */
public static void generate(String content, int width, int height, String imageType, OutputStream out) { public static void generate(String content, int width, int height, String imageType, OutputStream out) {
final BufferedImage image = generate(content, width, height); final BufferedImage image = generate(content, width, height);
@ -169,10 +167,10 @@ public class QrCodeUtil {
/** /**
* 生成二维码到输出流 * 生成二维码到输出流
* *
* @param content 文本内容 * @param content 文本内容
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @param imageType 图片类型图片扩展名{@link ImgUtil} * @param imageType 图片类型图片扩展名{@link ImgUtil}
* @param out 目标流 * @param out 目标流
* @since 4.1.2 * @since 4.1.2
*/ */
public static void generate(String content, QrConfig config, String imageType, OutputStream out) { public static void generate(String content, QrConfig config, String imageType, OutputStream out) {
@ -184,8 +182,8 @@ public class QrCodeUtil {
* 生成二维码图片 * 生成二维码图片
* *
* @param content 文本内容 * @param content 文本内容
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @return 二维码图片黑白 * @return 二维码图片黑白
*/ */
public static BufferedImage generate(String content, int width, int height) { public static BufferedImage generate(String content, int width, int height) {
@ -196,9 +194,9 @@ public class QrCodeUtil {
* 生成二维码或条形码图片 * 生成二维码或条形码图片
* *
* @param content 文本内容 * @param content 文本内容
* @param format 格式可选二维码或者条形码 * @param format 格式可选二维码或者条形码
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @return 二维码图片黑白 * @return 二维码图片黑白
*/ */
public static BufferedImage generate(String content, BarcodeFormat format, int width, int height) { public static BufferedImage generate(String content, BarcodeFormat format, int width, int height) {
@ -209,7 +207,7 @@ public class QrCodeUtil {
* 生成二维码图片 * 生成二维码图片
* *
* @param content 文本内容 * @param content 文本内容
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @return 二维码图片黑白 * @return 二维码图片黑白
* @since 4.1.2 * @since 4.1.2
*/ */
@ -222,8 +220,8 @@ public class QrCodeUtil {
* 只有二维码时QrConfig中的图片才有效 * 只有二维码时QrConfig中的图片才有效
* *
* @param content 文本内容 * @param content 文本内容
* @param format 格式可选二维码条形码等 * @param format 格式可选二维码条形码等
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @return 二维码图片黑白 * @return 二维码图片黑白
* @since 4.1.14 * @since 4.1.14
*/ */
@ -256,12 +254,13 @@ public class QrCodeUtil {
} }
// ------------------------------------------------------------------------------------------------------------------- encode // ------------------------------------------------------------------------------------------------------------------- encode
/** /**
* 将文本内容编码为二维码 * 将文本内容编码为二维码
* *
* @param content 文本内容 * @param content 文本内容
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @return {@link BitMatrix} * @return {@link BitMatrix}
*/ */
public static BitMatrix encode(String content, int width, int height) { public static BitMatrix encode(String content, int width, int height) {
@ -272,7 +271,7 @@ public class QrCodeUtil {
* 将文本内容编码为二维码 * 将文本内容编码为二维码
* *
* @param content 文本内容 * @param content 文本内容
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @return {@link BitMatrix} * @return {@link BitMatrix}
* @since 4.1.2 * @since 4.1.2
*/ */
@ -284,9 +283,9 @@ public class QrCodeUtil {
* 将文本内容编码为条形码或二维码 * 将文本内容编码为条形码或二维码
* *
* @param content 文本内容 * @param content 文本内容
* @param format 格式枚举 * @param format 格式枚举
* @param width 宽度 * @param width 宽度
* @param height 高度 * @param height 高度
* @return {@link BitMatrix} * @return {@link BitMatrix}
*/ */
public static BitMatrix encode(String content, BarcodeFormat format, int width, int height) { public static BitMatrix encode(String content, BarcodeFormat format, int width, int height) {
@ -297,8 +296,8 @@ public class QrCodeUtil {
* 将文本内容编码为条形码或二维码 * 将文本内容编码为条形码或二维码
* *
* @param content 文本内容 * @param content 文本内容
* @param format 格式枚举 * @param format 格式枚举
* @param config 二维码配置包括长边距颜色等 * @param config 二维码配置包括长边距颜色等
* @return {@link BitMatrix} * @return {@link BitMatrix}
* @since 4.1.2 * @since 4.1.2
*/ */
@ -319,6 +318,7 @@ public class QrCodeUtil {
} }
// ------------------------------------------------------------------------------------------------------------------- decode // ------------------------------------------------------------------------------------------------------------------- decode
/** /**
* 解码二维码图片为文本 * 解码二维码图片为文本
* *
@ -352,8 +352,8 @@ public class QrCodeUtil {
/** /**
* 将二维码图片解码为文本 * 将二维码图片解码为文本
* *
* @param image {@link Image} 二维码图片 * @param image {@link Image} 二维码图片
* @param isTryHarder 是否优化精度 * @param isTryHarder 是否优化精度
* @param isPureBarcode 是否使用复杂模式扫描带logo的二维码设为true * @param isPureBarcode 是否使用复杂模式扫描带logo的二维码设为true
* @return 解码后的文本 * @return 解码后的文本
* @since 4.3.1 * @since 4.3.1
@ -390,7 +390,7 @@ public class QrCodeUtil {
/** /**
* BitMatrix转BufferedImage * BitMatrix转BufferedImage
* *
* @param matrix BitMatrix * @param matrix BitMatrix
* @param foreColor 前景色 * @param foreColor 前景色
* @param backColor 背景色(null表示透明背景) * @param backColor 背景色(null表示透明背景)
* @return BufferedImage * @return BufferedImage
@ -402,9 +402,9 @@ public class QrCodeUtil {
BufferedImage image = new BufferedImage(width, height, null == backColor ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); BufferedImage image = new BufferedImage(width, height, null == backColor ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
if(matrix.get(x, y)) { if (matrix.get(x, y)) {
image.setRGB(x, y, foreColor); image.setRGB(x, y, foreColor);
} else if(null != backColor){ } else if (null != backColor) {
image.setRGB(x, y, backColor); image.setRGB(x, y, backColor);
} }
} }

View File

@ -1,16 +1,14 @@
package cn.hutool.extra.qrcode; package cn.hutool.extra.qrcode;
import java.awt.Color;
import java.io.File;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import java.awt.Color;
import java.io.File;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
/** /**
* 二维码工具类单元测试 * 二维码工具类单元测试
@ -61,7 +59,7 @@ public class QrCodeUtilTest {
System.out.println(base64); System.out.println(base64);
byte[] bytes = FileUtil.readBytes( byte[] bytes = FileUtil.readBytes(
new File("e:/pic/qr.png")); new File("d:/test/qr.png"));
String encode = Base64.encode(bytes); String encode = Base64.encode(bytes);
String base641 = QrCodeUtil.generateAsBase64("http://hutool.cn/", new QrConfig(400, 400), "png", encode); String base641 = QrCodeUtil.generateAsBase64("http://hutool.cn/", new QrConfig(400, 400), "png", encode);
System.out.println(base641); System.out.println(base641);