首页 > 编程语言 >JAVA对于图片的花式操作(不定期更新)

JAVA对于图片的花式操作(不定期更新)

时间:2024-10-29 15:45:02浏览次数:8  
标签:return String url 不定期 new JAVA null public 花式

JAVA对于图片的花式操作(不定期更新)

MultipartFile 转 Base64字符串

/**
 * MultipartFile文件转bash64字符串
 *
 * @param multiPartFile  文件流
 * @param isPrefix       是否需要前缀
 * @return
 */
public static String multiPartFileToBase64String(
											MultipartFile multiPartFile, 
											boolean isPrefix) {
    String baseStr = null;
    BASE64Encoder encoder = new BASE64Encoder();
    try {
        baseStr = encoder.encode(multiPartFile.getBytes());
        baseStr = baseStr.replaceAll("\r\n", "");
        if (isPrefix) {
            baseStr = "data:image/jpeg;base64," + baseStr;
        }
    } catch (IOException e) {
    }
    return baseStr;
}

图片url 转 Base64字符串

/**
 * 图片URL转Base64编码
 *
 * @param imagePath 图片URL
 * @param isPrefix  是否需要前缀
 * @return Base64编码
 */
public static String imageUrlToBase64(String imagePath, boolean isPrefix) {
    ByteArrayOutputStream outPut = new ByteArrayOutputStream();
    byte[] data = new byte[1024];
    InputStream inStream = null;
    try {
        // 创建URL
        URL url = new URL(imagePath);
        // 创建链接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(10 * 1000);
        if (conn.getResponseCode() != 200) {
            //连接失败/链接失效/图片不存在
            return "fail";
        }
        inStream = conn.getInputStream();
        int len = -1;
        while ((len = inStream.read(data)) != -1) {
            outPut.write(data, 0, len);
        }
        // 对字节数组Base64编码
        byte[] encode = Base64.getEncoder().encode(outPut.toByteArray());
        if (isPrefix) {
            String res = String.format("%s%s", "data:image/jpeg;base64,", new String(encode));
            return res;
        }
        return new String(encode);

    } catch (Exception e) {
    } finally {
        try {
            inStream.close();
        } catch (Exception e) {
        }
    }
}

图片url 转 MultipartFile

/**
 * 在线图片url转成MultipartFile对象
 *
 * @param url  图片url
 * @return
 */
public static MultipartFile imgUrlToMultiPartFile(String url) {
    URLConnection connection = null;
    InputStream inputStream = null;
    byte[] bytes = null;
    try {
        connection = new URL(url).openConnection();
        inputStream = connection.getInputStream();
        bytes = StreamUtils.copyToByteArray(inputStream);
    } catch (Exception e) {
        log.error(e.toString());
    }
    String contentType = connection.getContentType();
    String[] contentTypes = contentType.split("/");
    String filename = "file." + contentTypes[1];
    return new ByteArrayMultipartFile(bytes, filename, contentType);
}

图片url 转 File流

/**
 * url资源转化为file流
 *
 * @param url   图片url
 * @return
 */
public static File urlToFile(URL url) {
    InputStream is = null;
    File file = null;
    FileOutputStream fos = null;
    try {
        file = File.createTempFile("tmp", null);
        URLConnection urlConn = null;
        urlConn = url.openConnection();
        is = urlConn.getInputStream();
        fos = new FileOutputStream(file);
        byte[] buffer = new byte[4096];
        int length;
        while ((length = is.read(buffer)) > 0) {
            fos.write(buffer, 0, length);
        }
        return file;
    } catch (Exception e) {
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (Exception e) {
            }
        }
        if (fos != null) {
            try {
                fos.close();
            } catch (Exception e) {
            }
        }
    }
}

base64图片 压缩

引入依赖

<dependency>
	<groupId>net.coobird</groupId>
	<artifactId>thumbnailator</artifactId>
	<version>0.4.20</version>
</dependency>

代码编写

    /**
     * 目标大小不可设置太过准确,也不可太小,例如:需要压缩至150k以下的图片,那就传入140或者100左右的一个值即可
     *
     * @param imgBase64      原图片base64,含不含前缀【data:image/jpeg;base64,】都可
     * @param targetSize     压缩图片目标大小,默认100KB
     * @param throwException 出错时是否报错
     * @return 返回的base64内容不含【data:image/jpeg;base64,】前缀
     */
    public static String compressPic(String imgBase64, int targetSize, boolean throwException){
        if(StringUtils.isEmpty(imgBase64)){
            log.error("imgBase64 param not null ......");
            if(throwException){
                throw new MixException(BusinessErrorEnum.BASE_PARAM_FORMAT);
            }
        }
        targetSize = targetSize <= 0 ? 100 : targetSize;
        String newBase64 = imgBase64;
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;
        try {
            if(imgBase64.startsWith("data:")){
                imgBase64 = imgBase64.split(",")[1];
            }
            // 解码 Base64 图片数据
            byte[] imageBytes = Base64.getDecoder().decode(imgBase64);
            // 计算图片大小(KB)
            float imageOriginalSize = (float) imageBytes.length / 1024;
            log.info("--------------compressedImageBytes#imageOriginalSize(Byte) = {}", imageOriginalSize);
            //图片大小已经比目标值小,直接返回原图base64
            if(imageOriginalSize < targetSize){
                return newBase64;
            }
            // 创建输出流,用于存储压缩后的图片数据
            outputStream = new ByteArrayOutputStream();
            int index = 0;
            byte[] compressedImageBytes = imageBytes;
            // 图片大小压缩比例
            BigDecimal scale = new BigDecimal(1.0f);
            float quality = targetSize / imageOriginalSize;
            // 先进行质量压缩,如果质量压缩大小最终高于目标值,那就进行图片大小压缩
            while (scale.floatValue() >= 0.1 && compressedImageBytes.length / 1024 > targetSize){
                // 创建输入流,读取解码后的图片数据
                inputStream = new ByteArrayInputStream(imageBytes);
                outputStream.reset();
                Thumbnails.of(inputStream)
                        .scale(scale.floatValue())
                        .outputFormat("jpg")
                        .outputQuality(quality)
                        .toOutputStream(outputStream);
                // 获取压缩后的图片数据
                compressedImageBytes = outputStream.toByteArray();
                scale = scale.subtract(new BigDecimal(0.05f));
                ++index;
                log.info("--------------compressedImageBytes#index = {},scale = {}, nowSize = {}", index, scale.floatValue(), compressedImageBytes.length / 1024);
            }

            byte[] encode = Base64.getEncoder().encode(compressedImageBytes);
            newBase64 = new String(encode);
            log.info("--------------compressedImageBytes#nowImgSize(Byte) = {}", compressedImageBytes.length / 1024);
        }catch (Exception e){
            log.error("compressPic business error:", e);
            if(throwException){
                throw new MixException(BusinessErrorEnum.BASE_SERVER_UNKNOWN);
            }
        }finally {
            // 关闭流
            try {
                if(inputStream != null){
                    inputStream.close();
                }
                if(outputStream != null){
                    outputStream.close();
                }
            } catch (Exception e) {
                log.error("compressPic close stream error:", e);
                if(throwException){
                    throw new MixException(BusinessErrorEnum.BASE_SERVER_UNKNOWN);
                }
            }

        }
        return newBase64;
    }

抠图

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import java.io.*;

@Slf4j
public class ImageUtil {

    private final static String PNG = "png";

    private final static String JPG = "jpg";

    private final static String JPEG = "jpeg";

    private final static long TWO_MB = 1024 * 1024 * 2;
    /**
     * 切割图片,以左上角坐标为起点,切割指定宽高的图片
     * @param file
     * @param faceDetectVo
     * @return
     */
    public static MultipartFile slicingImage(InputStream file, String fileType, FaceDetectVo faceDetectVo){
        // 读取原始图片
        Integer width = faceDetectVo.getW();
        Integer high = faceDetectVo.getH();
        Integer x = faceDetectVo.getX();
        Integer y = faceDetectVo.getY();
        try {
            BufferedImage originalImage = ImageIO.read(file);
            int maxWidth = originalImage.getWidth(); // 获取原图的宽度
            int maxHigh= originalImage.getHeight(); // 获取原图的高度
            Color backgroundColor = getDominantColor(originalImage); // 获取原图的背景色
            // 校验参数
            x = x > 0 ? x : 0;
            y = y > 0 ? y : 0;
            width = width > 0 ? width : 0;
            high = high > 0 ? high : 0;
            width = x + width > maxWidth ? maxWidth - x: width;
            high = y + high > maxHigh ? maxHigh - y : high;
            BufferedImage subImage = originalImage.getSubimage(x, y, width, high);
            // 处理png格式的
            if (PNG.equals(fileType)){
                // 创建带背景颜色的新图像
                BufferedImage imageWithBackground = new BufferedImage(width, high, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = imageWithBackground.createGraphics();
                g2d.setColor(backgroundColor);
                g2d.fillRect(0,0, width, high);
                g2d.drawImage(subImage, 0, 0, null);
                g2d.dispose();
                MultipartFile multipartFile = convertBufferedImageToMultipartFile(subImage, "data.png", PNG);
                // 如果把jpg的图片后缀手动改为png,读取文件流的时候会文件变大,这种情况给他改为jpg
                if (multipartFile.getSize() > TWO_MB){
                    multipartFile = convertBufferedImageToMultipartFile(subImage, "data.jpg", JPG);
                    log.info("抠图大小大于2mb, 尝试转为jpg, 文件大小为: {}", multipartFile.getSize());
                }
                System.out.println("图片切分完成!");
                return multipartFile;
            }
            // 处理jpg, jpeg格式的
            // 创建带背景颜色的新图像
            BufferedImage imageWithBackground = new BufferedImage(width, high, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = imageWithBackground.createGraphics();
            g2d.setColor(backgroundColor);
            g2d.fillRect(0,0, width, high);
            g2d.drawImage(subImage, 0, 0, null);
            g2d.dispose();
            MultipartFile multipartFile = convertBufferedImageToMultipartFile(imageWithBackground, "data." + fileType, fileType);
            System.out.println("图片切分完成!");
            return multipartFile;
        } catch (IOException e) {
            log.error("图片切分失败!", e);
        } catch (RasterFormatException e) {
            log.info("切分坐标超出图片范围,请检查坐标设置。");
        }
        return null;
    }


    // 获取原图的背景色(可以改进为更复杂的算法)
    private static Color getDominantColor(BufferedImage image) {
        // 这里简单返回左上角像素的颜色作为背景色
        return new Color(image.getRGB(0, 0));
    }

    private static MultipartFile convertBufferedImageToMultipartFile(BufferedImage image, String fileName, String fileType) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, fileType, baos);
        InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        return new MultipartFile() {
            @Override
            public String getName() {
                return fileName;
            }
            @Override
            public String getOriginalFilename() {
                return fileName;
            }
            @Override
            public String getContentType() {
                return "image/" + fileType;
            }
            @Override
            public boolean isEmpty() {
                return baos.size() == 0;
            }
            @Override
            public long getSize() {
                return baos.size();
            }
            @Override
            public byte[] getBytes() throws IOException {
                return baos.toByteArray();
            }
            @Override
            public InputStream getInputStream() throws IOException {
                return inputStream;
            }
            @Override
            public void transferTo(File dest) throws IOException, IllegalStateException {
                // 这里可以实现文件转移逻辑
            }
        };
    }

    public static String getFileType(MultipartFile file) {
        String fileName = file.getOriginalFilename().toLowerCase();

        if (fileName.endsWith(StringPool.DOT + PNG)) {
            return PNG;
        }
        if (fileName.endsWith(StringPool.DOT + JPG)) {
            return JPG;
        }
        if (fileName.endsWith(StringPool.DOT + JPEG)) {
            return JPEG;
        }else {
            return PNG;
        }

    }
}

标签:return,String,url,不定期,new,JAVA,null,public,花式
From: https://blog.csdn.net/m0_63164811/article/details/143329507

相关文章

  • Java 23 新特性一览 + Java 24 新动态抢先看
    最近Oracle发布了Java编程语言和虚拟机的最新版本:Java23。作为Java21之后的第二个非LTS版本,该如果你还没了解过,那就一起了解一下吧(内含赠书)。最后,我们再一起看看Java24新动态。Java23 新特性通过ProjectAmber提供的语言特性JEP455:PrimitiveTypesinPatterns,i......
  • Java 中的类型推断是如何工作的?_2
    在Java中,类型推断是编译时进行的过程,它可以自动推导出表达式的类型、减少代码冗余及增强可读性。Java的类型推断通过以下方式工作:自动推导泛型参数类型、省略冗余类型信息、简化Lambda表达式的编写。特别是在Java8及以后的版本中,类型推断的特性得到了极大加强。单独展开描述,自动......
  • java计算机毕业设计翰明教育教学管理系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着教育事业的不断发展,学校规模的扩大以及教育管理要求的日益提高,传统的教育教学管理方式已经难以满足需求。在当今数字化时代,教育领域也迫切需......
  • 【java】RSA前后端互通
    后端importjavax.crypto.Cipher;importjava.security.KeyFactory;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;importjava.util.Base64;publi......
  • 异常处理汇总-Java&Mendix&Spark&SQL&etc...
    1.MyBatis映射问题执行计算过程中出现错误,错误消息:MappedStatementscollectiondoesnotcontainvaluefor... 问题原因:configure.xml文件中未配置对应路径。2. java:Annotationprocessingisnotsupportedformodulecycles.Pleaseensurethatallmodulesfrom......
  • 机票电子行程单如何批量查验?Java机票电子行程单查验接口示例
    机票电子行程单来了,它方便了人们的出行。现如今,随着旅游、差旅市场的回暖与线上业务的蓬勃发展,机票电子行程单的需求量急剧攀升,如何高效且准确地查验这些电子行程单成为许多企业和财务部门关注的焦点。传统的人工查验流程耗时且易出错,尤其在行程单数量巨大的情况下,费时费力。......
  • 2024前端面试训练计划-高频题-JavaScript基础篇
    具体内容结构(可作为回答思路)为:简略回答,详细回答1、JavaScript有几种数据类型?简略回答JavaScript共有八种数据类型,分别是Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。详细回答具体来说,分为两种类型:原始数据类型和引用数据类型:原始数据类型......
  • Java:String类(超详解!)
    一.常用方法......
  • 机票电子行程单如何批量查验?Java机票电子行程单查验接口示例-发票查验接口
    机票电子行程单来了,它方便了人们的出行。现如今,随着旅游、差旅市场的回暖与线上业务的蓬勃发展,机票电子行程单的需求量急剧攀升,如何高效且准确地查验这些电子行程单成为许多企业和财务部门关注的焦点。传统的人工查验流程耗时且易出错,尤其在行程单数量巨大的情况下,费时费力......
  • java计算机毕业设计成都医学院考研信息交流平台(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高等教育的普及和就业压力的增加,越来越多的本科毕业生选择继续深造,攻读硕士学位。成都医学院作为四川省的一所重要医学院校,吸引了大量学生报考其......