项目需要获取服务器上人的签名,有的人签名不是透明底图,需要对图片进行处理,获取图片流数据处理后返回base64位编码,也可以指定文件路径保存下来
色差范围,根据红绿蓝平均值来,个人的处理图片不同,值也不同
一:使用hutool的方法
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
二、工具类
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import sun.misc.BASE64Encoder;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Author ekkcole
* @remark 图片链接转为base64编码
*/
public class UrlToBase64Util {
//base64前缀
private static final String BASE64_PREFIX="data:image/png;base64,";
public static void main(String[] args) throws Exception {
String url="https://localhost:8080/upload/file/20221101/test.png";
System.out.println(BASE64_PREFIX+imageUrlToBase64(url));
}
/**
* 图片URL转Base64编码
*
* @param imgUrl 图片URL
* @return Base64编码
*/
public static String imageUrlToBase64(String imgUrl) {
InputStream is = null;
ByteArrayOutputStream outStream = null;
try {
if (!ObjectUtils.isEmpty(imgUrl)) {
HttpResponse res = HttpRequest.get(imgUrl).execute();
// 获取输入流
is = res.bodyStream();
outStream = new ByteArrayOutputStream();
//创建一个Buffer字符串
byte[] buffer = new byte[1024];
//每次读取的字符串长度,如果为-1,代表全部读取完毕
int len = 0;
//使用输入流从buffer里把数据读取出来
while ((len = is.read(buffer)) != -1) {
//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
outStream.write(buffer, 0, len);
}
// 对字节数组Base64编码
return encode(outStream.toByteArray());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (outStream != null) {
outStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 图片转字符串
*
* @param image 图片Buffer
* @return Base64编码
*/
public static String encode(byte[] image) {
BASE64Encoder decoder = new BASE64Encoder();
return replaceEnter(decoder.encode(image));
}
/**
* 字符替换
*
* @param str 字符串
* @return 替换后的字符串
*/
public static String replaceEnter(String str) {
String reg = "[\n-\r]";
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(str);
return m.replaceAll("");
}
}
三、实现方法
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.ekkcole.utils.UrlToBase64Util;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 获取服务器上图片抠图并返回base64位图片数据
*/
public class KouTuStream {
// 抠纯白背景,色差范围0~255
// public static int color_range = 210;
// 自定义的背景色,可以根据红绿蓝的平均值写
public static int color_range = 120;
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
// 服务器图片
String imgUrl="https://xxxxx.cn//upload/image/20210903/16410394627191873.png";
HttpResponse res = HttpRequest.get(imgUrl).execute();
InputStream is = res.bodyStream();
BufferedImage image = ImageIO.read(is);
// 高度和宽度
int height = image.getHeight();
int width = image.getWidth();
// 生产背景透明和内容透明的图片
ImageIcon imageIcon = new ImageIcon(image);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics(); // 获取画笔
g2D.drawImage(imageIcon.getImage(), 0, 0, null); // 绘制Image的图片
int alpha = 0; // 图片透明度
// 外层遍历是Y轴的像素
for (int y = bufferedImage.getMinY(); y < bufferedImage.getHeight(); y++) {
// 内层遍历是X轴的像素
for (int x = bufferedImage.getMinX(); x < bufferedImage.getWidth(); x++) {
int rgb = bufferedImage.getRGB(x, y);
// 对当前颜色判断是否在指定区间内
if (colorInRange(rgb)) {
alpha = 0;
} else {
// 设置为不透明
alpha = 255;
}
// #AARRGGBB 最前两位为透明度
rgb = (alpha << 24) | (rgb & 0x00ffffff);
bufferedImage.setRGB(x, y, rgb);
}
}
// 绘制设置了RGB的新图片
g2D.drawImage(bufferedImage, 0, 0, null);
// 生成输出流图片为PNG
ByteArrayOutputStream outStream= new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", outStream);
// 也可以指定文件路径保存
// ImageIO.write(bufferedImage, "png", new File("C:\\Users\\ron\\Desktop\\测试图\\16410394627191873(1).png"));
System.out.println("data:image/png;base64," + UrlToBase64Util.encode(outStream.toByteArray()));
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "毫秒");
System.out.println("抠图成功");
}
// 判断是背景还是内容
public static boolean colorInRange(int color) {
int red = (color & 0xff0000) >> 16;// 获取color(RGB)中R位
int green = (color & 0x00ff00) >> 8;// 获取color(RGB)中G位
int blue = (color & 0x0000ff);// 获取color(RGB)中B位
System.out.println("red+ = " + red + ",green+ = " + green + ",blue+ = " + blue);
// 通过RGB三分量来判断当前颜色是否在指定的颜色区间内
if (red >= color_range && green >= color_range && blue >= color_range) {
return true;
}
return false;
}
}