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)

大家都在看

  • Docker Maven构建缓存spring boot依赖包

    背景 每次通过 docker build ‘xxx’ 的时候,总是会去maven镜像下载一大堆Jar包,平均每次build都要在3分钟左右,效率非常低下,于…

    数据库 2023年6月6日
    084
  • 条件控制

    1. 顺序结构 java代码顺序执行 2. 选择结构 if语句 格式 if(结果为booblean类型的表达式){ 语句体; } if(结果为booblean类型的表达式){ 语句…

    数据库 2023年6月14日
    048
  • centos安装chrome和解决chrom点击打不开页面的问题

    1、去官网下载chrom的rpm包 2、进入到下载包的目录,执行:yum -y localinstall google-chrome-stable_current_x86_64.r…

    数据库 2023年6月11日
    082
  • RadonDB MySQL on K8s 2.1.3 发布!

    RadonDB MySQL Kubernetes 于 3 月 24 日正式发布新版本 2.1.3 。该版本主要基于在 2.1.2 进行功能优化和升级。 首先感谢 @andyli02…

    数据库 2023年5月24日
    083
  • bat 脚本启用及禁用网卡

    启用网卡 需要以管理员身份运行bat脚本 netsh interface set interface "Npcap Loopback Adapter" enab…

    数据库 2023年6月9日
    0115
  • 第五届蓝帽杯-溯源取证wp

    直接使用vmdk文件创建虚拟机,结果弹出提示 点击全部允许之后,进不去系统,到达了initramfs页面 由于提供的vmdk文件只有1G大小,将其转回raw文件,发现有10个G的大…

    数据库 2023年6月11日
    0102
  • 从零开始搭建高可用的k8s集群

    一、环境准备 使用Hyper-V虚拟机功能搭建三台Centos虚拟机系统,配置好静态IP,分别为k8s-node1(192.168.0.8),k8s-node2(192.168.0…

    数据库 2023年6月14日
    077
  • 数据库多表查询 联合查询 增删改查

    插入 方式一 语法: insert into 表名 (字段名,…) values (值,…); 特点: 1、要求值的类型和字段的类型要一致或兼容 2、字段的个数和顺序不一定…

    数据库 2023年6月16日
    0135
  • Java redisTemplate 使用 increment序列化问题

    添加key: ValueOperations redisTemplate.setValueSerializer(new StringRedisSerializer()); // 设…

    数据库 2023年6月9日
    099
  • 计算字符串中连续出现最多的字符串和长度

    public static void main(String[] args) { // 定义的字符&#x4E3…

    数据库 2023年6月11日
    075
  • 设计模式之抽象工厂

    一、抽象工厂:不管是简单工厂还是工厂方法,他们创建的都是同一类对象,有时候需要一组一组的创建对象,如果需要创建一组对象,抽象工厂是最好的方式,而抽象工厂的目的旨在创建一组包含多种不…

    数据库 2023年6月14日
    068
  • MySQL 回表

    MySQL 回表 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。 一、简述 回表,顾名思义就是回到表中,也就是先通过普通索引扫描出数据所在的行,再通过行主键ID 取出索引中未包含…

    数据库 2023年5月24日
    079
  • Pisa-Proxy SQL 解析之 Lex & Yacc

    一、前言 1.1 作者介绍 王波,SphereEx MeshLab 研发工程师,目前专注于 Database Mesh,Cloud Native 的研发。Linux,llvm,ya…

    数据库 2023年6月16日
    098
  • MySQL之自关联查询

    假设要设计两张表,一张省份表(provinces),一张城市表(citys) 省份表结构 id ptitle 城市表结构 id ctitle proid(表示城市所属的省,对应着省…

    数据库 2023年5月24日
    0109
  • 容器化 | 一文搞定镜像构建方式选型

    作者:安树博 青云科技 PaaS 中间件开发工程师从事 PaaS 中间件服务(Redis/Memcached 等)开发工作,热衷对 NoSQL 数据库领域内技术的学习与研究 官方镜…

    数据库 2023年5月24日
    071
  • MySQL建表语句生成Golang代码

    1. 背景 对于后台开发新的需求时,一般会先进行各种表的设计,写各个表的建表语句 然后根据建立的表,写对应的model代码、基础的增删改查代码(基础的增删改查服务可以划入DAO(D…

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