java转换图片格式,生成webp图片文件
公司最近的新项目,有移动端,所以需要对普通图片进行压缩,减少图片的大小。这样既能较少用户耗费的流量,又能提高用户浏览速度,而且图片质量基本上和压缩前保持不变,有利于提升用户体验。
- webp简介
- webp环境配置
- webp转换工具类
- 可能出现的异常
- 图片上传controller demo
- jar包上传到nexus私服
webp简介
- WebP是谷歌的图片格式,java 类库imageio 是不支持此种格式的。目前除了在线转换以及工具以外,第三方类库转webp格式大致有:
- linux:Google libwebp 既是类库也可以在命令行调用
- Python:Python Image Library(PIL)及其分支 https://pypi.python.org/pypi/PIL 不太了解
- Java:luciad/webp-imageio https://bitbucket.org/luciad/webp-imageio/src windows / linux亲测可用
webp环境配置
- 本例使用的webp的环境:
- Windows 10 专业版,Windows 7 x86 ,Windows 7 x64
- Linux server244 3.10.0-514.21.1.el7.x86_64 #1 SMP Thu May 25 17:04:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
- 环境配置所需资源下载:webp开发工具包(java)
- 这里使用的webp-imageio这个包,需要根据操作系统和jdk位数,来编译一些环境配置文件(通常使用cmake编译,这个我不是很懂),但是我怀疑最终是通过修改native方法来实现的。
- 配置环境:将对应的dll或者os文件,放到安装的jdk的bin下面(java.library.path下),比如我的电脑里如下图:
- 注意:.dll文件是windows用的,.os文件是linux的。当然,资源包里还准备的有macos的
- linux下:建议写一个Test.java,然后敲命令
javac Test
编译,再敲命令java Test
运行编译后的文件,就能输出当前系统下的java.library.path
public class Test{
public static void main(String[] args) {
String a = System.getProperty("java.library.path");
System.out.println(a);
}
}
例如我的是:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
然后把对应的.os文件放在/usr/java/packages/lib/amd64里面(没有这个文件夹就自己新建个)
webp工具类
- 配好环境后,应该就可以直接跑工具类的main方法了
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
/**
* Description: 普通格式图片转换为webp格式图片 工具类
* 耗时稍长,建议异步调用
*
* @author XU SAN DUO
* Date: 2018/1/11 15:13
* @version 1.0
*/
public class ImageToWebpUtil {
public static final String WEBP = "webp";
public static final String WEBP_SUFFIX = ".webp";
/**
* 1. 传入图片文件路径,返回file对象
* @param imgFilePath 图片文件路径(比如转换图片为F:/1.png 那么转换后的webp文件为:F:/1.png.webp)
* @return
*/
public static File toWebpFile(String imgFilePath){
File imgFile = new File(imgFilePath);
File webpFile = new File(imgFilePath + WEBP_SUFFIX);
try {
BufferedImage bufferedImage = ImageIO.read(imgFile);
ImageIO.write(bufferedImage, WEBP, webpFile);
}catch (Exception e){
e.printStackTrace();
}
return webpFile;
}
/**
* 2. 传入图片url,返回file对象
* @param imgUrlPath 图片路径url
* @param webpFilePath 生成的webp文件路径
* @return
*/
public static File toWebpFile(String imgUrlPath, String webpFilePath){
File webpFile = new File(webpFilePath);
try {
BufferedImage bufferedImage = ImageIO.read(new URL(imgUrlPath));
ImageIO.write(bufferedImage, WEBP, webpFile);
}catch (Exception e){
e.printStackTrace();
}
return webpFile;
}
/**
* 3. 传入图片文件路径,返回InputStream
* @param imgFilePath 图片文件路径(比如转换图片为F:/1.png 那么转换后的webp文件为:F:/1.png.webp)
* @return
*/
public static InputStream toWebpStream(String imgFilePath){
File imgFile = new File(imgFilePath);
File webpFile = new File(imgFilePath + WEBP_SUFFIX);
FileInputStream fis = null;
try {
BufferedImage bufferedImage = ImageIO.read(imgFile);
ImageIO.write(bufferedImage, WEBP, webpFile);
fis = new FileInputStream(webpFile);
}catch (Exception e){
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return fis;
}
/**
* 4. 传入图片url,返回InputStream
* @param imgUrlPath 图片路径url
* @param webpFilePath 生成的webp文件路径
* @return
*/
public static InputStream toWebpStream(String imgUrlPath, String webpFilePath){
File webpFile = new File(webpFilePath);
FileInputStream fis = null;
try {
BufferedImage bufferedImage = ImageIO.read(new URL(imgUrlPath));
ImageIO.write(bufferedImage, WEBP, webpFile);
fis = new FileInputStream(webpFile);
}catch (Exception e){
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return fis;
}
// 测试
public static void main(String[] args) {
long start = System.currentTimeMillis();
// 1. test 传入图片文件路径,返回file对象
// String imgFilePath = "F:/test.png";
// File result = toWebpFile(imgFilePath);
// 2. test 传入图片url,返回file对象
String imgUrlPath = "http://pic151.nipic.com/file/20171228/22164794_210348306033_2.jpg";
String webpFilePath = "F:/xiche.jpg.webp";
File result = toWebpFile(imgUrlPath,webpFilePath);
// 3. test 传入图片文件路径,返回InputStream
// String imgFilePath = "F:/test.png";
// InputStream result = toWebpStream(imgFilePath);
// 4. test 传入图片url,返回InputStream
// String imgUrlPath = "http://pic151.nipic.com/file/20171228/22164794_210348306033_2.jpg";
// String webpFilePath = "F:/xiche.jpg.webp";
// InputStream result = toWebpStream(imgUrlPath,webpFilePath);
long end = System.currentTimeMillis();
System.out.println("用时:"+(end - start) + " ms ; return ---->");
System.out.print(result);
}
}
可能出现的异常
java.lang.UnsatisfiedLinkError: no webp-imageio in java.library.path
,说明环境没有配置好,解决办法:请重新仔细看一下上面说的环境配置java.lang.NoClassDefFoundError: Could not initialize class com.luciad.imageio.webp.WebPWriteParam
,虽然把对应的配置文件放在指定位置,但是是在应用程序启动之后放进去的,解决办法:重启你的application
图片上传controller demo
- 这只是一个简易示例。(用的阿里的oss)
/**
*
* 文件上传
* @param file 图片对象
* @param fileUrl 要存放的ossKey
* return
*/
@ApiOperation(value = "上传图片", httpMethod = "POST", notes = "上传图片")
@RequestMapping(value = "/uploadImg", method = RequestMethod.POST)
@ResponseBody
public ResultVO<Object> uploadImg(MultipartFile file, String fileUrl) {
ResultVO<Object> result = new ResultVO<>();
String logoUrlFileUrl = "";
try {
if (!file.isEmpty()) {
logoUrlFileUrl += OSSFileOptUtils.uploadFile3(file, fileUrl, evnType);
result.setData(logoUrlFileUrl);
result.setStatus(ResultStatusEnum.OK.getValue());
result.setMessage("上传图片成功");
final String imgUrl = OssConstant.img_url_prefix + logoUrlFileUrl;
final String webpKey = logoUrlFileUrl.substring(1) + ImageToWebpUtil.WEBP_SUFFIX;
final String webpFilePath = this.webpFolder + file.getOriginalFilename()
+ ImageToWebpUtil.WEBP_SUFFIX;
new Thread(new Runnable(){
@Override
public void run() {
File webp = ImageToWebpUtil.toWebpFile(imgUrl,webpFilePath);
OSSFileOptUtils.uploadFile(OssConstant.shanghai_bucket_name,webpKey,webp,1);
log.info("【已上传webp文件:"+webpKey+"】");
}
}).start();
}
} catch (Exception e) {
e.printStackTrace();
result.setStatus(ResultStatusEnum.ERROR.getValue());
result.setMessage("上传图片失败!");
log.error("上传失败", e);
}
return result;
}
jar包上传到nexus私服
- 这个webp的作者目前还没有把它上传到maven repository,而我们实际开发中,公司里一般都有自己搭建的nexus私服。所以这里就再啰嗦一点,写一下如何上传webp.jar到nexus私服
仅介绍命令行上传
安装nexus私服,略。但是要记住 ++id++ 和 ++url++
<distributionManagement> <repository> <id>nexus-releases</id> <url>http://192.168.0.240:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>nexus-snapshots</id> <url>http://192.168.0.240:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement>
假如现在有一个java项目,配置了maven。那么,需要在项目所依赖的maven的setting.xml中添加对这个nexus的配置:id,username,password一定要正确
<server> <id>nexus-releases</id> <username>admin</username> <password>admin123</password> </server> <server> <id>nexus-snapshots</id> <username>admin</username> <password>admin123</password> </server>
进入到项目根目录下,执行命令:(参数应该一看就懂)
- 为什么要到项目根目录下执行:因为项目引用了setting.xml,而里面配置了username和password。这样就相当于有了权限
mvn deploy:deploy-file -DgroupId=com.luciad.imageio -DartifactId=webp -Dversion=0.4.2 -Dpackaging=jar -Dfile=E:/a/webp-imageio-0.4.2.jar -Durl=http://192.168.0.240:8081/repository/maven-releases/ -DrepositoryId=nexus-releases