Java实现将图片压缩到指定大小

Java实现将图片压缩到指定大小

    
    public static File compressImageToSize(MultipartFile multipartFile, double targetSizeMB, String fileName) throws IOException {
        //读取原始图片
        //获取InputStream字节输入流,通过输入流可读取文件内容。
        InputStream inputStream = multipartFile.getInputStream();
        //从InputStream中读取图片数据,并将其转换为一个BufferedImage对象(包含图像的像素、宽度和高度等信息。通过这个对象,可以对图像进行缩放、旋转和裁剪等操作)
        BufferedImage originalImage = ImageIO.read(inputStream);

        //从文件名中提取扩展名
        String extension = fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".")) : ".jpg";

        //获取原始图片宽度
        int originalWidth = originalImage.getWidth();
        //获取原始图片高度
        int originalHeight = originalImage.getHeight();
        /* 计算缩放因子
         * originalWidth * originalHeight / 1000000.0:计算原始图片的面积(以平方米为单位),1000000.0:将像素转换为兆字节所需的因子,因为1MB = 1000000字节,而每个像素通常占用1字节(假设没有压缩)
         * targetSizeMB / (originalWidth * originalHeight / 1000000.0):计算目标大小与原始大小的比值
         * Math.sqrt(targetSizeMB / (originalWidth * originalHeight / 1000000.0)):对上述比值取平方根,得到缩放因子。
         * 文件大小 = 分辨率(宽度像素数 × 高度像素数)× 颜色深度(位深度)/ 8
         * eg.
         * 假设缩放因子为k,那么缩放后的图像宽度为originalWidth * k,高度为originalHeight * k。
         * 缩放后的图像面积为(originalWidth * k) * (originalHeight * k) = originalWidth * originalHeight * k^2。
         * 我们希望缩放后的图像面积接近目标大小,即originalWidth * originalHeight * k^2 ≈ targetSizeMB * 1000000。
         * 将上述等式两边同时除以originalWidth * originalHeight,得到k^2 ≈ targetSizeMB * 1000000 / (originalWidth * originalHeight)。
         * 对两边同时开平方,得到k ≈ sqrt(targetSizeMB * 1000000 / (originalWidth * originalHeight))。
         * */
        double scaleFactor = Math.sqrt(targetSizeMB / (originalWidth * originalHeight / 1000000.0));

        //计算新的图片尺寸
        int newWidth = (int) (originalWidth * scaleFactor);
        int newHeight = (int) (originalHeight * scaleFactor);

        //使用imgscalr进行缩放
        /* 使用imgscalr库进行图像缩放,Scalr.resize()方法接受以下参数:
         * originalImage:要缩放的原始图像。
         * Scalr.Method.QUALITY:缩放算法,这里选择QUALITY,表示优先保证图像质量。
         * Scalr.Mode.AUTOMATIC:自动选择最佳的缩放模式。
         * newWidth和newHeight:缩放后的图像尺寸。
         * Scalr.OP_ANTIALIAS:抗锯齿选项,用于平滑图像边缘。
         * */
        BufferedImage scaledImage = Scalr.resize(originalImage, Scalr.Method.QUALITY, Scalr.Mode.AUTOMATIC, newWidth, newHeight, Scalr.OP_ANTIALIAS);

        //创建一个临时文件,使用原始文件名(不包括扩展名)和扩展名
        File compressedFile = new File(fileName);
        //JVM退出时,这个文件将被删除。
        compressedFile.deleteOnExit();

        //写入文件
        //OutputStream类型的变量os是一个用于存储输出流对象的引用,通过这个引用,可以调用输出流的方法来执行写操作,例如将数据写入文件或发送数据到网络。
        OutputStream os = null;
        try{
            //创建一个FileOutputStream实例,用于向文件compressedFile写入数据;FileOutputStream实例被赋值变量os,os变量现在持有了一个指向compressedFile文件的输出流,可以通过这个流来写入数据。
            os = new FileOutputStream(compressedFile);
            //将scaledImage(BufferedImage对象)以extension.substring(1)(去掉扩展名前的点)格式写入到os指定的输出流中。这通常用于将处理后的图像保存到文件中写入到os(OutputStream对象,表示图像数据将被写入的目标位置)中。
            ImageIO.write(scaledImage, extension.substring(1), os);
        } catch (IOException e) {
            throw new IOException("Failed to write the image to file.", e);
        }finally {
            //关闭输入流(inputStream)和输出流(os),若不关闭,会出现JVM退出时临时文件删除不了的问题
            if(os != null){
                try{
                    //关闭multipartFile对应的inputStream输入流
                    inputStream.close();
                }catch (IOException e) {
                    log.info(e.getMessage());
                }finally {
                    try {
                        //关闭compressedFile对应的OutputStream输出流
                        os.close();
                    }catch (IOException e) {
                        log.info(e.getMessage());
                    }
                }
            }
        }
        return compressedFile;
    }
    
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用ImageIO类和Java Advanced Imaging (JAI)库来实现图片压缩。以下是一个简单的代码示例,可以将图片压缩指定大小不失帧: ```java import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.media.jai.JAI; import javax.media.jai.RenderedOp; import com.sun.media.jai.codec.ImageCodec; import com.sun.media.jai.codec.ImageEncoder; import com.sun.media.jai.codec.JPEGEncodeParam; public class ImageCompressor { public static void compressImage(File inputFile, File outputFile, long maxSize) throws IOException { BufferedImage image = ImageIO.read(inputFile); //读取图片文件 int width = image.getWidth(); int height = image.getHeight(); long imageSize = inputFile.length(); while (imageSize > maxSize) { width *= 0.9; //缩小图片宽度 height *= 0.9; //缩小图片高度 RenderedOp resizedImage = JAI.create("SubsampleAverage", image, width, height); //缩小图片 ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", outputFile, null); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(resizedImage); param.setQuality(0.8f, false); //设置压缩质量 encoder.setParam(param); encoder.encode(resizedImage); //保存压缩后的图片 imageSize = outputFile.length(); } } } ``` 上述代码中,我们首先读取输入文件的图片,并获取图片的宽度、高度及大小。然后循环运行,每次缩小图片的宽度和高度,直到图片大小小于等于指定的最大值。在每次缩小图片后,我们使用JAI库创建一个渲染操作对象,对其进行平均子采样,并使用ImageCodec库中的JPEG编码器将图片保存到输出文件中。渲染操作时,我们可以通过指定宽度和高度来控制图片的大小,从而达到压缩图片的目的。在保存图片时,我们可以通过设置JPEG编码参数的质量参数来控制压缩质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值