Java-图片裁切白底-并写入excel单元格-byte-inputstream互转-写入文件
- 补充说明
https://codeleading.com/article/2429918744/ 需要看背景是透明的测试失败,白色的为测试 之前收集也有问题,也处理不了白色背景的
https://blog.csdn.net/qq_23625847/article/details/125009501(看起来没哟裁切的代码) https://blog.csdn.net/qq_53216148/article/details/122304153
byte[] bytes =onlineImage2byte(url);
bytes = ImageUtils.cropEmptyEdge(null, bytes, 0, false);//图片裁切白底
ExcelWriter writer = ExcelUtil.getWriter();
ExcelUtils.writeImage(writer, 2, i + 2, bytes, HSSFWorkbook.PICTURE_TYPE_JPEG, false); //写入excel单元格
package cn.jiangjiesheng.edu.utils;
import cn.jiangjiesheng.bootstrap.commons.exception.BizzException;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.regex.Pattern;
/**
* 如果要实现
* <p>
* 改造来自下面两个的结合
* https://blog.csdn.net/wohaqiyi/article/details/109266869
* https://blog.csdn.net/zds12345sdfs/article/details/119736965
* <p>
* 耗时还是比较大的,最好上传文件时就处理裁切
* <p>
* 另外可以参考 https://www.jianshu.com/p/8b3542e6a571 ,但是裁切有丢失边缘
*/
public class ImageUtils {
public static int color_range = 210;
public static Pattern pattern = Pattern.compile("[0-9]*");
public static boolean isNo(String str) {
return pattern.matcher(str).matches();
}
public static void main(String[] args) throws Exception {
try {
FileInputStream fileInputStream = new FileInputStream(new File("D:\\test\\未处理1.png"));
byte[] bytes = new byte[0];
try {
bytes = input2byte(fileInputStream);
} catch (IOException e) {
e.printStackTrace();
}
//实测 传0,50 都能实现裁切掉多余的空白区域
byte[] bytes1 = cropEmptyEdge(null, bytes, 0, false);
writeBytes2File(bytes1, "D:\\test\\未处理1-new.png");
// 第二组测试
fileInputStream = new FileInputStream(new File("D:\\test\\图片1.png"));
bytes = new byte[0];
try {
bytes = input2byte(fileInputStream);
} catch (IOException e) {
e.printStackTrace();
}
//实测 传0,50 都能实现裁切掉多余的空白区域
bytes1 = cropEmptyEdge(null, bytes, 0, false);
writeBytes2File(bytes1, "D:\\test\\图片1-new.png");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 实测 传0、50 都能实现裁切掉多余的空白区域
* 这个接口的返回需要 byte[]、InputStream 、直接写入文件,都能做到
* 是否需要把背景改成透明
*/
public static byte[] cropEmptyEdge(InputStream inputStream, byte[] bytes, int rcb, boolean setTransparentBackground) throws Exception {
try {
if (inputStream == null && (bytes == null || bytes.length == 0)) {
throw new BizzException("inputStream、bytes不能同时为空,优先读取inputStream");
}
if (inputStream == null) {
inputStream = byte2Input(bytes);
}
// 如果是MultipartFile类型,那么自身也有转换成流的方法:is = file.getInputStream();
BufferedImage bi = ImageIO.read(inputStream);
Image image = (Image) bi;
ImageIcon imageIcon = new ImageIcon(image);
BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
int alpha = 0;
//横坐标最小值
int minx = 0;
//纵坐标最小值
int miny = 0;
//横坐标最大值
int maxx = 0;
//纵坐标最大值
int maxy = 0;
color_range = 255 - rcb; // 0
for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage
.getHeight(); j1++) {
for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage
.getWidth(); j2++) {
int rgb = bufferedImage.getRGB(j2, j1);
if (colorInRange(rgb)) {
alpha = 0;
} else {
alpha = 255;
if (minx == 0 && miny == 0) {
minx = j2;
miny = j1;
} else {
if (minx > j2) {
minx = j2;
}
if (miny > j1) {
miny = j1;
}
}
if (maxx == 0 && maxy == 0) {
maxx = j2;
maxy = j1;
} else {
if (maxx < j2) {
maxx = j2;
}
if (maxy < j1) {
maxy = j1;
}
}
}
//这里如果需要把背景设置透明,就打开
if (setTransparentBackground) {
rgb = (alpha << 24) | (rgb & 0x00ffffff);
bufferedImage.setRGB(j2, j1, rgb);
}
}
}
g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
if (minx > 0 || miny > 0) {
//+-10是为了预留10像素的边距
minx -= 10;
miny -= 10;
if (minx < 10) {
minx = 10;
}
if (miny < 10) {
miny = 10;
}
bufferedImage = bufferedImage.getSubimage(minx, miny, maxx - minx + 10, maxy - miny + 10);
}
// ImageIO.write(bufferedImage, "png", file);// 直接输出文件
return bufferedImageToByteArray(bufferedImage);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
}
}
}
if (bytes != null) {
return bytes;
} else {
if (inputStream == null) {
return null;
}
return input2byte(inputStream);
}
}
public static boolean colorInRange(int color) {
//if(color != -1){
// System.out.println(color);
//}
int red = (color & 0xff0000) >> 16;
int green = (color & 0x00ff00) >> 8;
int blue = (color & 0x0000ff);
if (red >= color_range && green >= color_range && blue >= color_range) {
return true;
}
return false;
}
/**
* bytes 转 InputStream
* <p>
* 互转 https://www.cnblogs.com/lukelook/p/11067725.html
*
* @param bytes
* @return
*/
public static InputStream byte2Input(byte[] bytes) {
return new ByteArrayInputStream(bytes);
}
/**
* InputStream 转 bytes
*
* @param inputStream
* @return
* @throws IOException
*/
public static final byte[] input2byte(InputStream inputStream) throws IOException {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int rc = 0;
while ((rc = inputStream.read(buff, 0, 1024)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in2b = swapStream.toByteArray();
return in2b;
}
/**
* bytes 转 文件
*
* @param bytes
* @param filePath 没有会自动新建
* @throws IOException
*/
public static void writeBytes2File(byte[] bytes, String filePath) throws IOException {
OutputStream out = new FileOutputStream(filePath);
InputStream is = new ByteArrayInputStream(bytes);
byte[] buff = new byte[1024];
int len = 0;
while ((len = is.read(buff)) != -1) {
out.write(buff, 0, len);
}
is.close();
out.close();
}
public static byte[] bufferedImageToByteArray(BufferedImage image) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
return os.toByteArray();
}
}
package cn.jiangjiesheng.edu.utils;
import cn.hutool.poi.excel.ExcelWriter;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
public class ExcelUtils {
/**
* @param writer
* @param x 单元格x轴坐标
* @param y 单元格y轴坐标
* @param pictureData 图片二进制数据
* @param picType 图片格式 HSSFWorkbook.*
*/
public static void writeImage(ExcelWriter writer, int x, int y, byte[] pictureData, int picType, boolean closeWrite) {
Sheet sheet = writer.getSheet();
//改到提前,给每行都设置,无论当前行有没有图片
//Row row = sheet.getRow(y);
//设置行高
//row.setHeightInPoints(40);
Drawing drawingPatriarch = sheet.createDrawingPatriarch();
//设置图片单元格位置
ClientAnchor anchor = drawingPatriarch.createAnchor(0, 0, 0, 0, x, y, x + 1, y + 1);
//随单元格改变位置和大小
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
//添加图片
int pictureIndex = sheet.getWorkbook().addPicture(pictureData, picType);
drawingPatriarch.createPicture(anchor, pictureIndex);
if (closeWrite) {
//一般后续逻辑没完成,不做关闭
//另外也要注意 writer.flush(out, true); 会关闭,关闭了就不能写入了
writer.close();
}
}
}
/**
* 在线图片转换成base64字符串
* @param imgURL
* @return
*/
public String imageToBase64ByOnline(String imgURL, Boolean handleCropImage2Base64) {
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
byte[] bytes = imageToByteByOnline(imgURL, handleCropImage2Base64);
return encoder.encode(bytes);
}
public byte[] imageToByteByOnline(String imgURL,Boolean handleCropImage2Base64) {
if (handleCropImage2Base64 == null) {
handleCropImage2Base64 = bizzConfig.getEnableHandleCropImage2Base64();
}
ByteArrayOutputStream data = new ByteArrayOutputStream();
try {
// 创建URL
URL url = new URL(imgURL);
byte[] by = new byte[1024];
// 创建链接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
InputStream is = conn.getInputStream();
// 将内容读取内存中
int len = -1;
while ((len = is.read(by)) != -1) {
data.write(by, 0, len);
}
// 关闭流
is.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] imageByte = data.toByteArray();
if (handleCropImage2Base64 != null && handleCropImage2Base64) {
try {
byte[] cropImageByte = ImageUtils.cropEmptyEdge(null, imageByte, 0, false);
if (cropImageByte != null) {
imageByte = cropImageByte;
} else {
log.warn("裁切图片失败,返回为空,url:{}", imgURL);
}
} catch (Exception e) {
log.warn("裁切图片出现异常,url:{},异常:{}", imgURL, e);
}
}
return imageByte;
}
/**
* 本地图片转换成base64字符串
* @param imgFile
* @return
*/
public String imageToBase64ByLocal(String imgFile) {
InputStream in = null;
byte[] data = null;
// 读取图片字节数组
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
/**
* base64字符串转换成图片
* @param imgStr
* @param imgFilePath
* @return
*/
public boolean base64ToImage(String imgStr,String imgFilePath) {
if (StringUtils.isEmpty(imgStr)) {
return false;
}
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
return true;
} catch (Exception e) {
return false;
}
}
正文到此结束