在线图片转压缩base64、在线图片合并压缩转base64

在线图片转压缩base64、在线图片合并压缩转base64

package com.froad.credit.common.util;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;


@Slf4j
public class ImageCompressionUtils {

    final static long SIZE_2MB = 2048 * 1024;
    final static long SIZE_1MB = 1024 * 1024;
    final static long SIZE_512KB = 512 * 1024;
    final static long SIZE_256KB = 256 * 1024;
    final static long SIZE_128KB = 128 * 1024;
    final static long SIZE_64KB = 64 * 1024;
    final static long SIZE_32KB = 32 * 1024;


    /**
     * 将网络上的图片转换为Base64编码的字符串。
     * 该方法首先从给定的URL加载图片,然后根据图片大小生成缩略图,并将其压缩为指定的质量和尺寸。
     * 最后,将压缩后的图片数据编码为Base64字符串。
     *
     * @param imgURL 图片的URL地址。
     * @param tempPath 保存临时图片的文件路径。
     * @return 压缩后图片的Base64编码字符串。
     * @throws IOException 如果读取或处理图片时发生错误。
     */
    public static String imageToBase64ByOnline(String imagePrefix,String imgURL,String tempPath,String base64Prefix) throws IOException {
        // 记录开始时间,用于日志记录处理耗时
        long start = System.currentTimeMillis();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        String base64;
        String filePath = "";
        try {
            log.info("开始处理imgURL:{}",imagePrefix+imgURL);
            // 从URL读取图片
            BufferedImage read = ImageIO.read(new URL(imagePrefix+imgURL));
            log.info("读取图片耗时:{}", System.currentTimeMillis() - start);
            // 生成唯一的文件名,用于保存压缩后的图片
            //生成新图片名称
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            String fileString = df.format(new Date()) + "_" + new Random().nextInt(1000) + ".jpg";
            filePath = tempPath + fileString;
            // 创建缩略图,并根据图片大小调整缩放比例,保存到指定路径
            Thumbnails.of(read).scale(1d).toFile(filePath);

            File f = new File(filePath);
            // 根据文件大小确定压缩策略,包括缩放比例和压缩质量
            float scale = 0.0f;
            float quality = 0.0f;
            long fileSize = f.length();
            if (fileSize > SIZE_2MB) {
                scale = 0.15f;
                quality = 0.3f;
            }else if (fileSize > SIZE_1MB) {
                scale = 0.2f;
                quality = 0.3f;
            } else if (fileSize >  SIZE_512KB) {
                scale = 0.3f;
                quality = 0.4f;
            } else if (fileSize > SIZE_256KB) {
                scale = 0.4f;
                quality = 0.5f;
            } else if (fileSize > SIZE_128KB) {
                scale = 0.5f;
                quality = 0.6f;
            } else if (fileSize >  SIZE_64KB) {
                scale = 0.7f;
                quality = 0.8f;
            } else if (fileSize > SIZE_32KB) {
                scale = 0.8f;
                quality = 0.9f;
            }else {
                scale = 0.8f;
                quality = 0.9f;
            }
            // 根据确定的缩放比例和压缩质量,对图片进行压缩,并将结果输出到ByteArrayOutputStream
            Thumbnails.of(filePath).scale(scale).outputQuality(quality).outputFormat("jpg").toOutputStream(out);
            // 将压缩后的图片数据转换为Base64编码字符串
            base64 =  new String(new Base64().encode((out.toByteArray())));
            // 记录图片压缩后的大小
            log.info("图片压缩后大小:{}", base64.length());
            // 记录图片压缩的耗时
            log.info("图片压缩耗时:{}", System.currentTimeMillis() - start);
        }finally {
            // 确保关闭ByteArrayOutputStream
            try{
                out.close();
            }catch (Exception e){
                // 记录关闭流时发生的异常
                log.error("关闭流异常:{}", e.getMessage(),e);
            }
            if(StringUtils.isNotBlank(filePath)){
                File file = new File(filePath);
                if(file.exists()){
                    // 删除临时文件
                    log.info("删除文件结果:{}", file.delete());
                }
            }
        }
       return base64Prefix+base64;
    }


    public static void saveDecodedBase64ImageToLocalFile(String base64ImageString, String filePath) throws IOException {
        byte[] imageBytes = new Base64().decode(base64ImageString);
        File file = new File(filePath);
        try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
            fileOutputStream.write(imageBytes);
        }
    }

    /**
     * 将在线图片合并为一张图片并转换为Base64编码。
     *
     * @param imagePrefix 图片前缀URL。
     * @param imagePaths 图片路径数组。
     * @param tempPath 临时文件存储路径。
     * @param horizontal 指定合并方式是否为水平合并。
     * @param vertical 指定合并方式是否为垂直合并。
     * @param scale 缩放比例。
     * @param quality 压缩质量。
     * @return 合并后的图片的Base64编码字符串。
     * @throws IOException 如果读取或处理图片时发生错误。
     */
    public static String mergeImageToBase64ByOnline(String imagePrefix,List<String> imagePaths,String tempPath, boolean horizontal, boolean vertical,double scale,double quality,String base64Prefix) throws IOException {
        // 存储下载的本地图片路径
        List<String> localImagePaths = new ArrayList<>();
        String base64;
        // 记录开始时间用于统计处理耗时
        long startTime = System.currentTimeMillis();
        try{
            // 格式化时间用于生成唯一的文件名
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            // 遍历图片路径数组,下载并处理每张图片
            for (String imagePath : imagePaths) {
                // 记录开始下载时间
                long downloadTime = System.currentTimeMillis();
                // 生成唯一的文件名
                String fileString = df.format(new Date()) + "_" + new Random().nextInt(1000) + ".jpg";
                // 拼接临时文件路径
                String filePath = tempPath + fileString;
                // 从URL读取图片
                BufferedImage read = ImageIO.read(new URL(imagePrefix+imagePath));
                // 缩放图片并保存到本地
                Thumbnails.of(read).scale(1d).toFile(filePath);
                // 将本地图片路径添加到列表
                localImagePaths.add(filePath);
                // 记录下载图片的耗时
                log.info("下载图片{}耗时:{}",imagePrefix+imagePath, System.currentTimeMillis() - downloadTime);
            }
            // 记录下载所有图片的总耗时
            log.info("下载图片总耗时:{}", System.currentTimeMillis() - startTime);
            // 创建 ByteArrayOutputStream 用于存储合并后的图片数据
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                // 合并本地图片,应用缩放和质量设置,将结果写入到 ByteArrayOutputStream
                Thumbnails.of(mergeImages(localImagePaths.toArray(new String[0]), horizontal, vertical)).scale(scale).outputQuality(quality).outputFormat("jpg").toOutputStream(out);
                // 将压缩后的图片数据转换为Base64编码字符串
                base64 = new String(new Base64().encode((out.toByteArray())));
            }finally {
                // 确保关闭 ByteArrayOutputStream
                try{
                    out.close();
                }catch (Exception e){
                    // 记录关闭流时发生的异常
                    log.error("关闭流异常:{}", e.getMessage(),e);
                }
            }
        }finally {
            // 遍历本地图片路径列表,删除已生成的临时文件
            for (String localImagePath : localImagePaths) {
                File file = new File(localImagePath);
                if(file.exists()){
                    // 记录删除文件的结果
                    log.info("删除文件{}结果:{}", localImagePath,file.delete());
                }
            }
            // 记录图片处理的总耗时
            log.info("图片处理耗时:{}", System.currentTimeMillis() - startTime);
        }
        return base64Prefix+base64;
    }

    /**
     * 合并多个图像为一个图像。
     * 根据参数horizontal和vertical的值,决定是水平合并还是垂直合并图像。
     *
     * @param imagePaths 图像文件路径的数组。
     * @param horizontal 指示是否水平合并图像的布尔值。
     * @param vertical 指示是否垂直合并图像的布尔值。
     * @return 合并后的图像作为BufferedImage对象。
     * @throws IOException 如果读取图像文件发生错误。
     */
    private static BufferedImage mergeImages(String[] imagePaths, boolean horizontal, boolean vertical) throws IOException {
        long start = System.currentTimeMillis();
        // 用于存储合并过程中的最后一张图像
        BufferedImage lastImage = null;
        for (String imagePath : imagePaths) {
            log.info("开始处理imagePath:{}",imagePath);
            if (lastImage == null) {
                // 读取第一张图像
                lastImage = ImageIO.read(new File(imagePath));
            } else {
                // 读取当前图像
                BufferedImage image = ImageIO.read(new File(imagePath));
                if (horizontal) {
                    // 水平合并:计算新图像的宽度和高度
                    // 计算合并后图片的宽度和高度
                    int width = lastImage.getWidth() + image.getWidth();
                    int height = Math.max(lastImage.getHeight(), image.getHeight());
                    // 创建一个新的BufferedImage用于存储合并后的图像
                    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                    // 获取绘图对象
                    Graphics graphics = bufferedImage.getGraphics();
                    // 在新图像上绘制上一张图像和当前图像
                    graphics.drawImage(lastImage, 0, 0, null);
                    graphics.drawImage(image, lastImage.getWidth(), 0, null);
                    // 释放绘图对象资源
                    graphics.dispose();
                    // 更新lastImage为合并后的图像
                    lastImage = bufferedImage;
                } else if (vertical) {
                    // 垂直合并:计算新图像的宽度和高度
                    // 计算合并后图片的宽度和高度
                    int width = Math.max(lastImage.getWidth(), image.getWidth());
                    int height = lastImage.getHeight() + image.getHeight();
                    // 创建一个新的BufferedImage用于存储合并后的图像
                    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                    // 获取绘图对象
                    Graphics graphics = bufferedImage.getGraphics();
                    // 在新图像上绘制上一张图像和当前图像
                    graphics.drawImage(lastImage, 0, 0, null);
                    graphics.drawImage(image, 0, lastImage.getHeight(), null);
                    // 释放绘图对象资源
                    graphics.dispose();
                    // 更新lastImage为合并后的图像
                    lastImage = bufferedImage;
                }
            }
        }
        log.info("合并图片耗时:{}", System.currentTimeMillis() - start);
        // 返回合并后的图像
        return lastImage;
    }

}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值