原创

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;
        }
    }
正文到此结束
本文目录