Java案例如何压缩本地图片?

wen java案例 9

本文目录导读:

Java案例如何压缩本地图片?

  1. 使用ImageIO(JDK自带)
  2. 使用Thumbnails库(推荐)
  3. 完整压缩工具类
  4. 推荐使用方式
  5. 注意事项

我来详细介绍Java压缩本地图片的几种常用方法。

使用ImageIO(JDK自带)

基本压缩示例

import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class ImageCompressExample {
    public static void compressImage(String sourcePath, String targetPath, float quality) throws IOException {
        // 读取原始图片
        File sourceFile = new File(sourcePath);
        BufferedImage originalImage = ImageIO.read(sourceFile);
        // 获取输出流
        FileOutputStream fos = new FileOutputStream(targetPath);
        ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
        // 获取JPEG写入器
        ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
        writer.setOutput(ios);
        // 设置压缩参数
        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(quality); // 0.0-1.0,值越小压缩越大
        // 写入图像
        writer.write(null, new javax.imageio.IIOImage(originalImage, null, null), param);
        // 关闭资源
        writer.dispose();
        ios.close();
        fos.close();
    }
    public static void main(String[] args) {
        try {
            compressImage("input.jpg", "output.jpg", 0.5f);
            System.out.println("图片压缩完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用Thumbnails库(推荐)

添加Maven依赖

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

压缩示例

import net.coobird.thumbnailator.Thumbnails;
import java.io.File;
import java.io.IOException;
public class ThumbnailsCompressExample {
    /**
     * 按质量压缩
     */
    public static void compressByQuality(String sourcePath, String targetPath, float quality) throws IOException {
        Thumbnails.of(sourcePath)
                .scale(1f)  // 保持原尺寸
                .outputQuality(quality)  // 压缩质量 0.0-1.0
                .toFile(targetPath);
    }
    /**
     * 按尺寸压缩
     */
    public static void compressBySize(String sourcePath, String targetPath, int width, int height) throws IOException {
        Thumbnails.of(sourcePath)
                .size(width, height)
                .outputQuality(0.8f)
                .toFile(targetPath);
    }
    /**
     * 按比例压缩
     */
    public static void compressByScale(String sourcePath, String targetPath, double scale) throws IOException {
        Thumbnails.of(sourcePath)
                .scale(scale)  // 0.0-1.0
                .outputQuality(0.8f)
                .toFile(targetPath);
    }
    /**
     * 批量压缩
     */
    public static void batchCompress(String sourceDir, String targetDir, float quality) throws IOException {
        File[] files = new File(sourceDir).listFiles((dir, name) -> 
            name.toLowerCase().endsWith(".jpg") || name.toLowerCase().endsWith(".png")
        );
        if (files != null) {
            for (File file : files) {
                String targetPath = targetDir + File.separator + "compressed_" + file.getName();
                compressByQuality(file.getAbsolutePath(), targetPath, quality);
                System.out.println("压缩完成: " + file.getName());
            }
        }
    }
    public static void main(String[] args) {
        try {
            // 按质量压缩
            compressByQuality("input.jpg", "output_quality.jpg", 0.5f);
            // 按尺寸压缩
            compressBySize("input.jpg", "output_size.jpg", 800, 600);
            // 按比例压缩
            compressByScale("input.jpg", "output_scale.jpg", 0.5);
            System.out.println("压缩完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

完整压缩工具类

import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;
public class ImageCompressUtil {
    /**
     * 图片压缩综合方法
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @param maxSize 最大文件大小(字节)
     * @param maxWidth 最大宽度
     * @param maxHeight 最大高度
     */
    public static void compressImage(String sourcePath, String targetPath, 
                                    long maxSize, int maxWidth, int maxHeight) throws IOException {
        File sourceFile = new File(sourcePath);
        File targetFile = new File(targetPath);
        // 读取原始图片
        BufferedImage originalImage = ImageIO.read(sourceFile);
        // 计算缩放尺寸
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();
        // 限制尺寸
        if (width > maxWidth) {
            height = (int) (height * (double) maxWidth / width);
            width = maxWidth;
        }
        if (height > maxHeight) {
            width = (int) (width * (double) maxHeight / height);
            height = maxHeight;
        }
        // 缩放图片
        BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = scaledImage.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
                          RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(originalImage, 0, 0, width, height, null);
        g.dispose();
        // 压缩质量调整
        float quality = 0.8f;
        String formatName = getFormatName(sourcePath);
        // 获取写入器
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
        ImageWriter writer = writers.next();
        // 设置输出
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
            writer.setOutput(ios);
            // 设置压缩参数
            ImageWriteParam param = writer.getDefaultWriteParam();
            if (param.canWriteCompressed()) {
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(quality);
            }
            // 写入图像
            writer.write(null, new IIOImage(scaledImage, null, null), param);
            // 检查文件大小,如果太大则降低质量
            byte[] imageBytes = baos.toByteArray();
            while (imageBytes.length > maxSize && quality > 0.1f) {
                quality -= 0.1f;
                baos.reset();
                try (ImageOutputStream ios2 = ImageIO.createImageOutputStream(baos)) {
                    writer.setOutput(ios2);
                    param.setCompressionQuality(quality);
                    writer.write(null, new IIOImage(scaledImage, null, null), param);
                    imageBytes = baos.toByteArray();
                }
            }
            // 写入目标文件
            try (FileOutputStream fos = new FileOutputStream(targetFile)) {
                fos.write(imageBytes);
            }
        }
        writer.dispose();
    }
    /**
     * 获取格式名称
     */
    private static String getFormatName(String fileName) {
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        if ("jpg".equals(extension) || "jpeg".equals(extension)) {
            return "jpg";
        } else if ("png".equals(extension)) {
            return "png";
        } else if ("gif".equals(extension)) {
            return "gif";
        }
        return "jpg";
    }
    /**
     * 简单的质量压缩
     */
    public static void simpleCompress(String sourcePath, String targetPath, float quality) throws IOException {
        BufferedImage image = ImageIO.read(new File(sourcePath));
        compressImageWithQuality(image, targetPath, quality);
    }
    private static void compressImageWithQuality(BufferedImage image, String targetPath, float quality) throws IOException {
        File targetFile = new File(targetPath);
        String formatName = getFormatName(targetPath);
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
        ImageWriter writer = writers.next();
        try (FileOutputStream fos = new FileOutputStream(targetFile);
             ImageOutputStream ios = ImageIO.createImageOutputStream(fos)) {
            writer.setOutput(ios);
            ImageWriteParam param = writer.getDefaultWriteParam();
            if (param.canWriteCompressed()) {
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(quality);
            }
            writer.write(null, new IIOImage(image, null, null), param);
        }
        writer.dispose();
    }
    public static void main(String[] args) {
        try {
            // 综合压缩
            compressImage("input.jpg", "output.jpg", 
                         500 * 1024, // 最大500KB
                         1920,       // 最大宽度
                         1080);      // 最大高度
            System.out.println("压缩完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

推荐使用方式

对于大多数场景,推荐使用 Thumbnails库,因为它:

  • API简洁易用
  • 支持多种压缩方式
  • 性能优秀
  • 内存管理好

如果不想引入第三方依赖,可以使用JDK自带的ImageIO,但需要更多的代码来确保质量和性能。

注意事项

  1. 质量选择:quality值0.0-1.0,一般建议0.5-0.8
  2. 格式选择:JPEG适合照片,PNG适合图标和文字
  3. 内存管理:处理大图片时注意JVM内存设置
  4. 异常处理:图片损坏或格式不支持时需要捕获异常
  5. 线程安全:ImageWriter不是线程安全的,多线程环境下需要各自创建实例

抱歉,评论功能暂时关闭!