JAVA根据指定大小压缩图片

    /**
     * 根据指定大小压缩图片
     *
     * @param sourceFilePath 源图片路径 + 文件名(例 “D:\\image\\aa.jpg”)
     * @param outFilePath    生成之后的图片路径 + 文件名(例 “D:\\image\\bb.jpg”)
     * @return 压缩质量后的图片字节数组
     */
    public static byte[] compressPicForScale(String sourceFilePath, String outFilePath) {

        if (StringUtils.isEmpty(sourceFilePath)) {
            return null;
        }

        // 指定图片大小,单位kb
        long desFileSize = 512;

        byte[] imageBytes = null;
        try {
            imageBytes = FileUtils.readFileToByteArray(new File(sourceFilePath));
            if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
                return imageBytes;
            }
            long srcSize = imageBytes.length;
            long size = srcSize / 1024;

            // 自动调节精度(经验数值)
            double accuracy;
            if (size < 900) {
                accuracy = 0.85;
            } else if (size < 2047) {
            
使用 Java 实现图片压缩指定大小可以采用二分法压缩的核心思路,以下是具体实现步骤及代码示例: ### 实现思路 1. **读取原始图片**:使用 Java 的 `ImageIO` 类读取原始图片文件。 2. **二分法压缩**:通过不断调整压缩质量,使用二分法找到满足指定大小要求的压缩质量。 3. **可选:按最大宽度自动缩放**:当压缩仍不够时,按最大宽度自动缩放图片。 4. **保存压缩后的图片**:使用 `ImageIO` 类将压缩后的图片保存到指定文件。 ### 代码示例 ```java import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; public class ImageCompressor { /** * 压缩图片指定大小 * @param originalImageFile 原始图片文件 * @param targetSizeKB 指定的目标大小(KB) * @param maxWidth 最大宽度,当压缩仍不够时按此宽度缩放 * @param outputFile 输出的压缩图片文件 * @throws IOException 读取或写入图片时可能抛出的异常 */ public static void compressImageToSize(File originalImageFile, int targetSizeKB, int maxWidth, File outputFile) throws IOException { // 读取原始图片 BufferedImage originalImage = ImageIO.read(originalImageFile); // 二分法压缩 float low = 0.0f; float high = 1.0f; float quality = 0.5f; while (low < high) { // 尝试当前质量压缩 File tempFile = File.createTempFile("temp", ".jpg"); compressImage(originalImage, quality, tempFile); // 检查压缩后的文件大小 long fileSize = tempFile.length() / 1024; // 转换为 KB if (fileSize > targetSizeKB) { high = quality; } else if (fileSize < targetSizeKB) { low = quality; } else { break; } // 更新质量 quality = (low + high) / 2; } // 检查最终压缩后的文件大小 File finalTempFile = File.createTempFile("final", ".jpg"); compressImage(originalImage, quality, finalTempFile); long finalFileSize = finalTempFile.length() / 1024; // 转换为 KB // 当压缩仍不够时,按最大宽度自动缩放 if (finalFileSize > targetSizeKB) { BufferedImage scaledImage = scaleImage(originalImage, maxWidth); compressImage(scaledImage, quality, outputFile); } else { // 复制临时文件到输出文件 java.nio.file.Files.copy(finalTempFile.toPath(), outputFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING); } } /** * 按指定质量压缩图片 * @param image 要压缩图片 * @param quality 压缩质量(0.0 - 1.0) * @param outputFile 输出的压缩图片文件 * @throws IOException 读取或写入图片时可能抛出的异常 */ private static void compressImage(BufferedImage image, float quality, File outputFile) throws IOException { // 获取 JPEG 图像写入器 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg"); ImageWriter writer = writers.next(); // 获取图像写入参数 ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); // 创建输出流 OutputStream outputStream = new FileOutputStream(outputFile); ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream); writer.setOutput(imageOutputStream); // 写入压缩后的图像 writer.write(null, new IIOImage(image, null, null), param); // 关闭资源 imageOutputStream.close(); outputStream.close(); writer.dispose(); } /** * 按最大宽度缩放图片 * @param originalImage 原始图片 * @param maxWidth 最大宽度 * @return 缩放后的图片 */ private static BufferedImage scaleImage(BufferedImage originalImage, int maxWidth) { int width = originalImage.getWidth(); int height = originalImage.getHeight(); if (width <= maxWidth) { return originalImage; } // 计算缩放比例 double ratio = (double) maxWidth / width; int newWidth = maxWidth; int newHeight = (int) (height * ratio); // 创建缩放后的图片 BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, originalImage.getType()); Graphics2D g2d = scaledImage.createGraphics(); g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null); g2d.dispose(); return scaledImage; } public static void main(String[] args) { try { File originalImageFile = new File("path/to/original/image.jpg"); int targetSizeKB = 100; // 指定的目标大小(KB) int maxWidth = 800; // 最大宽度 File outputFile = new File("path/to/output/image.jpg"); compressImageToSize(originalImageFile, targetSizeKB, maxWidth, outputFile); System.out.println("图片压缩成功!"); } catch (IOException e) { e.printStackTrace(); } } } ``` ### 代码解释 1. **`compressImageToSize` 方法**:该方法接收原始图片文件、目标大小(KB)、最大宽度和输出文件作为参数,使用二分法压缩图片,并在必要时按最大宽度缩放图片。 2. **`compressImage` 方法**:该方法按指定质量压缩图片,并将压缩后的图片保存到指定文件。 3. **`scaleImage` 方法**:该方法按最大宽度缩放图片,并返回缩放后的图片。 ### 单元测试示例 ```java import org.junit.jupiter.api.Test; import java.io.File; import static org.junit.jupiter.api.Assertions.assertTrue; public class ImageCompressorTest { @Test public void testCompressImageToSize() throws Exception { File originalImageFile = new File("path/to/original/image.jpg"); int targetSizeKB = 100; // 指定的目标大小(KB) int maxWidth = 800; // 最大宽度 File outputFile = new File("path/to/output/image.jpg"); ImageCompressor.compressImageToSize(originalImageFile, targetSizeKB, maxWidth, outputFile); // 检查输出文件是否存在 assertTrue(outputFile.exists()); // 检查输出文件大小是否在目标大小范围内 long fileSize = outputFile.length() / 1024; // 转换为 KB assertTrue(fileSize <= targetSizeKB); } } ``` ### 注意事项 - 请确保在运行代码前,将 `path/to/original/image.jpg` 和 `path/to/output/image.jpg` 替换为实际的文件路径。 - 该代码示例使用了 JUnit 5 进行单元测试,请确保在项目中添加 JUnit 5 的依赖。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值