哇哦,一个超级牛逼的图片格式!!使用它之后我们系统加载图片快了一倍!!! 图片格式转换webp学习!

什么是webp格式?

WebP 格式是一种图像文件格式。

它是由谷歌开发的,旨在提供一种高效的图像压缩方式,同时保持较好的图像质量。WebP 格式具有较小的文件体积,能够在一定程度上减少网络传输的数据量,提升网页加载速度。它支持有损压缩和无损压缩两种模式。

为什么要用webp格式?

  1. 减小文件大小
  2. 能显著降低图片文件的体积,节省存储空间。
  3. 减少网络传输的数据量,降低服务器的带宽压力。
  4. 提升加载效率
  5. 更快的加载速度可以改善用户体验。
  6. 快速加载的图片能让用户在浏览时感觉更流畅。
  7. 保持较好质量
  8. 在压缩过程中能较好地保留图像的细节和质量。

话不多说,上代码

首先 spring 三板斧

引入依赖:

因为webp在java中并没有上传到maven中央仓库,只能通过jar手动上传。点我下载文件

手动依赖方案:

<!--        图片格式转换为webp-->
<dependency>
    <groupId>com.github.nintha</groupId>
    <artifactId>webp-imageio-core</artifactId>
    <version>0.1.3</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/src/main/resources/libs/webp-imageio-core-0.1.3.jar</systemPath>
</dependency>

FileUtils

package cn.ideamake.file.common.utils;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.stream.StreamUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.ideamake.file.aop.MockMultipartFile;
import com.luciad.imageio.webp.WebPWriteParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Date;
import java.util.UUID;

@Slf4j
public class FileUtils {

    /**
     * 图片文件类型转换为webp格式
     * @return webp图片
     */
    public static File imagesToWebp(File file){
        try {
            String fileType = FileTypeUtil.getType(file);
            String outputWebpPath;
            if (!StrUtil.equalsAny(fileType, "jpg", "png", "jpeg")) {
                return null;
            }

            outputWebpPath = "/tmp/" + RandomUtil.randomString(32) + ".webp";
            // Obtain an image to encode from somewhere
            BufferedImage image = ImageIO.read(file);

            // Obtain a WebP ImageWriter instance
            ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/webp").next();

            // Configure encoding parameters
            WebPWriteParam writeParam = new WebPWriteParam(writer.getLocale());
            writeParam.setCompressionMode(WebPWriteParam.MODE_DEFAULT);

            // Configure the output on the ImageWriter
            writer.setOutput(new FileImageOutputStream(new File(outputWebpPath)));

            // Encode
            writer.write(null, new IIOImage(image, null, null), writeParam);

            return new File(outputWebpPath);
        } catch (Exception e) {
            log.error("上传失败", e);
            return null;
        }
    }

    public static MultipartFile imagesToWebp(MultipartFile multipartFile) throws IOException {
        File tmpFile = multipartFileToFile(multipartFile, "/tmp/multipartFileToFile"
                , RandomUtil.randomString(32) + "." + FileUtil.getSuffix(multipartFile.getOriginalFilename()));
        File file = imagesToWebp(tmpFile);
        return file == null ? multipartFile : new MockMultipartFile(file.getName(), FileUtil.getInputStream(file));
    }


    /**
     * MultipartFile类型文件转File
     * @return File类型文件
     */
    private static File multipartFileToFile(MultipartFile multipartFile, String filePath, String fileName){
        File f = null;
        File dir = new File(filePath);
        if (!dir.exists() && !dir.isDirectory()) {
            dir.mkdirs();
        }
        if(multipartFile.getSize() <= 0){
            multipartFile = null;
        } else {
            try {
                InputStream ins = multipartFile.getInputStream();
                f = new File(filePath + fileName);
                OutputStream os = Files.newOutputStream(f.toPath());
                int bytesRead = 0;
                byte[] buffer = new byte[8192];
                while ((bytesRead = ins.read(buffer, 0, 8192)) != -1){
                    os.write(buffer, 0, bytesRead);
                }
                os.close();
                ins.close();
            } catch (IOException e) {
                log.error("转换file文件失败:{}", e);
            }
        }
        return f;
    }

    public static byte[] imagesToWebp(byte[] bytes, String fileName){
        File file = imagesToWebp(FileUtil.writeBytes(bytes, "/tmp/multipartFileToFile/" + fileName));
        return file == null ? bytes : FileUtil.readBytes(file);
    }

}

方法可自行重载扩展。

需要返回 MultipartFile 文件格式康我 MockMultipartFile 类

/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.ideamake.file.aop;

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * Mock implementation of the {@link MultipartFile}
 * interface.
 *
 */
public class MockMultipartFile implements MultipartFile {

	private final String name;

	private final String originalFilename;

	@Nullable
	private final String contentType;

	private final byte[] content;


	/**
	 * Create a new MockMultipartFile with the given content.
	 * @param name the name of the file
	 * @param content the content of the file
	 */
	public MockMultipartFile(String name, @Nullable byte[] content) {
		this(name, name, null, content);
	}

	/**
	 * Create a new MockMultipartFile with the given content.
	 * @param name the name of the file
	 * @param contentStream the content of the file as stream
	 * @throws IOException if reading from the stream failed
	 */
	public MockMultipartFile(String name, InputStream contentStream) throws IOException {
		this(name, name, null, FileCopyUtils.copyToByteArray(contentStream));
	}

	/**
	 * Create a new MockMultipartFile with the given content.
	 * @param name the name of the file
	 * @param originalFilename the original filename (as on the client's machine)
	 * @param contentType the content type (if known)
	 * @param content the content of the file
	 */
	public MockMultipartFile(
			String name, @Nullable String originalFilename, @Nullable String contentType, @Nullable byte[] content) {

		Assert.hasLength(name, "Name must not be null");
		this.name = name;
		this.originalFilename = (originalFilename != null ? originalFilename : "");
		this.contentType = contentType;
		this.content = (content != null ? content : new byte[0]);
	}

	/**
	 * Create a new MockMultipartFile with the given content.
	 * @param name the name of the file
	 * @param originalFilename the original filename (as on the client's machine)
	 * @param contentType the content type (if known)
	 * @param contentStream the content of the file as stream
	 * @throws IOException if reading from the stream failed
	 */
	public MockMultipartFile(
			String name, @Nullable String originalFilename, @Nullable String contentType, InputStream contentStream)
			throws IOException {

		this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
	}


	@Override
	public String getName() {
		return this.name;
	}

	@Override
	public String getOriginalFilename() {
		return this.originalFilename;
	}

	@Override
	@Nullable
	public String getContentType() {
		return this.contentType;
	}

	@Override
	public boolean isEmpty() {
		return (this.content.length == 0);
	}

	@Override
	public long getSize() {
		return this.content.length;
	}

	@Override
	public byte[] getBytes() {
		return this.content;
	}

	@Override
	public InputStream getInputStream() {
		return new ByteArrayInputStream(this.content);
	}

	@Override
	public void transferTo(File dest) throws IOException, IllegalStateException {
		FileCopyUtils.copy(this.content, dest);
	}

}

效果展示:

图片展示

webp

image

jpg

image

大小展示

webp

image

jpg

image

压缩了50% 而且还能保质保证图片效果!

本文到此结束啦,希望对你有所帮助!如果害怕下次找不到笔者关注点一点!

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值