Java压缩图片

压缩图片

一、压缩原理

一张原始图像(1920×1080),如果每个像素32bit表示(RGBA),那么,图像需要的内存大小1920x1080x4 = 8294400 Byte
那图像为何可以压缩呢?因为它有很多冗余信息。

1、 空间冗余

空间冗余主要发生在单张图片
一幅图像表面上各采样点的颜色之间往往存在着空间连贯性,比如下图莉亚左下角的橱柜颜色相同,这些颜色相同的块就可以压缩。

比如说,第一行像素基本都一样,假设亮度值Y是这么存的[105比如说,第一行像素基本都一样,假设亮度值Y是这么存的[105 105 105…….105],如果共100个像素,那需要1Byte*100。
最简单的压缩:[105, 100],表示接下来100个像素的亮度都是105,那么只要2个字节,就能表示整行数据了

Java压缩图片

2、视觉冗余

人类的视觉系统由于受生理特性的限制,对于图像场的注意是非均匀的,人对细微的颜色差异感觉不明显。例如,人类视觉的一般分辨能力为26灰度等级,而一般的图像的量化采用的是28灰度等级,即存在视觉冗余。人类的听觉对某些信号反映不太敏感,使得压缩后再还原有允许范围的变化,人也感觉不出来。

Java压缩图片

二、编码

1、方式一

(1)、写工具类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.ImageIcon;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class imagesFiler {
    /**
     * 缩放图片(压缩图片质量,改变图片尺寸)
     * 若原图宽度小于新宽度,则宽度不变!
     * @param originalFile 原图片路径地址
     * @param resizedFile 压缩后输出路径地址
     * @param maxWidth 最大宽度
     * @param maxHeight 最大高度
     * @param newWidth 新的宽度
     * @param quality 图片质量参数 0.7f 相当于70%质量
     */
    public static void imageResize(File originalFile, File resizedFile,
                              int maxWidth,int maxHeight, float quality) throws IOException {

        if (quality > 1) {
            throw new IllegalArgumentException(
                    "图片质量需设置在0.1-1范围");
        }

        ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());
        Image i = ii.getImage();
        Image resizedImage = null;

        int iWidth = i.getWidth(null);
        int iHeight = i.getHeight(null);

        int newWidth = maxWidth;
        if(iWidth < maxWidth){
            newWidth = iWidth;
        }

        if (iWidth >= iHeight) {
            resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight)
                    / iWidth, Image.SCALE_SMOOTH);
        }

        int newHeight = maxHeight;
        if(iHeight < maxHeight){
            newHeight = iHeight;
        }

        if(resizedImage==null && iHeight >= iWidth){
            resizedImage = i.getScaledInstance((newHeight * iWidth) / iHeight,
                    newHeight, Image.SCALE_SMOOTH);
        }

        //此代码确保加载图像中的所有像素
        Image temp = new ImageIcon(resizedImage).getImage();

        //创建缓冲图像
        BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null),
                temp.getHeight(null), BufferedImage.TYPE_INT_RGB);

        //将图像复制到缓冲图像
        Graphics g = bufferedImage.createGraphics();

       //清除背景并绘制图像。
        g.setColor(Color.white);
        g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
        g.drawImage(temp, 0, 0, null);
        g.dispose();

        float softenFactor = 0.05f;
        float[] softenArray = { 0, softenFactor, 0, softenFactor,
                1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0 };
        Kernel kernel = new Kernel(3, 3, softenArray);
        ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
        bufferedImage = cOp.filter(bufferedImage, null);

        //将jpeg写入文件
        FileOutputStream out = new FileOutputStream(resizedFile);

         //将图像编码为jpeg数据流
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);

        JPEGEncodeParam param = encoder
                .getDefaultJPEGEncodeParam(bufferedImage);

        param.setQuality(quality, true);

        encoder.setJPEGEncodeParam(param);
        encoder.encode(bufferedImage);
    }

}

(2)、测试

public class demo {
    public static void main(String[] args) throws Exception{
    //需要压缩的图片地址     aaa.jpg为需要压缩的图片
    File customaryFile = new File("");
    //压缩过后输出的路径地址    ddd.jpg 可进行设置为任意名称
    File compressAfter = new File("");
        imagesFiler.imageResize(customaryFile,compressAfter,1200,2500,0.8f);
    }
}

2、方式2

(1)、导入jar包

maven


    net.coobird
    thumbnailator
    0.4.8

gradle

implementation group: 'net.coobird', name: 'thumbnailator', version: '0.4.14'

其他工具去maven 搜索Thumbnailator

(2)、测试

Thumbnails.of("原图文件的路径")
        .scale(1f)
        .outputQuality(0.5f)
        .toFile("压缩后文件的路径");

迷途者寻影而行

Original: https://www.cnblogs.com/pkkyh/p/14780353.html
Author: 迷途者寻影而行
Title: Java压缩图片

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/575747/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 第八章:变量、常量和基础类型

    本篇翻译自《Practical Go Lessons》 Chapter 8: Variables, constants and basic types 1 你将在本章中学到什么? …

    数据库 2023年6月6日
    0124
  • MySQL操作题(mysql_V20190307)

    DB操作题(mysql_V20190307) 登陆数据库 MYSQL -H LOCALHOST -U ROOT -P 创建DEMO01数据库 CREATE DATABASE DEM…

    数据库 2023年6月9日
    059
  • day39-网络编程01

    Java网络编程01 1.网络相关的概念 1.1网络通信和网络 *网络通信 概念:两台设备之间通过网络实现数据传输 网络通信:将数据通过网络从一台设备传输到另一台设备 java.n…

    数据库 2023年6月11日
    0102
  • COLA 架构规范定义

    基础架构图 Adapter 适配层:对前端展示的路由和适配。 VO:返回给前端的对象 assembler:将 responseDTO 转换为 VO web:处理页面请求的 Cont…

    数据库 2023年6月6日
    0109
  • tiler–python实现的有趣的自定义马赛克图像拼接工具

    最近在github中发现了一个有趣的小工具,tiler github链接https://github.com/nuno-faria/tiler 具体介绍请直接去github,这里只…

    数据库 2023年6月11日
    088
  • JUC学习笔记(六)

    JUC 中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过多时 Lock 锁的频繁操作。这三种辅助类为: CountDownLatch: 减少计数 CyclicBar…

    数据库 2023年6月6日
    097
  • 存储过程procedure、触发器trigger

    一、存储过程procedure MySQL 5.0 版本开始支持存储过程。 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对…

    数据库 2023年6月9日
    083
  • 15. 三数之和

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。 注意:答案…

    数据库 2023年6月16日
    072
  • jenkins

    jenkins 1.简介 1.1 SVN介绍 1.2 Maven介绍 1.3 Ant介绍 1.4 Gradle介绍 1.5 jenkins工作原理 1.6 jenkins特点 2….

    数据库 2023年6月14日
    059
  • 6_SSM

    一. ssm整合 1.1 项目创建 1.1.1 创建Maven项目 创建一个普通的Maven-web项目,名称为ssm 记得勾选上Create from archetype然后选择…

    数据库 2023年6月11日
    074
  • 线程简介

    线程简介以多线程在Windows操作系统中的运行模式为例:Windows操作系统是 多任务操作系统,它以进程为 单位。每个独立执行的程序都被称为 进程( 比如正在运行的QQ是一个进…

    数据库 2023年6月16日
    0124
  • Java 线程是如何启动的?

    Java启动线程的代码: 根据以上代码分析,并从源码了解启动线程发生了以下事件来完成启动线程: 1、Java 创建线程和启动 2、调用本地方法 start0(); 3、JVM 中 …

    数据库 2023年6月16日
    084
  • git开发常用命令

    1.基本命令git branch 查看本地分支git branch -r 查看远程分支git checkout xxx 切换分支git pull origin master //从…

    数据库 2023年6月9日
    090
  • MySql Explain字段解析

    MySql Explain字段解析 id id列表示select的序号,查询Sql中有几个select就会有几个id。 id的值越大,该查询的优先级超高。 select_type …

    数据库 2023年5月24日
    086
  • linux根目录无法查看文件执行ls卡死无反应执行df -h 也同样没反应的处理方法

    问题现象: 1、执行 df -h 卡死没反应,执行 df -hl&#xA0;可以正常显示; 2、执行 &#xA0;ll /&#xA0;或 ls /&…

    数据库 2023年6月11日
    091
  • MySQL45讲之保证高可用

    本文主要介绍 MySQL 主备延迟,延迟产生的原因和主备切换策略。 主备延迟 主备同步过程中主要有三个时间点: [En] There are three main time poi…

    数据库 2023年5月24日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球