用Java将ico格式转 PNG/JPG等格式

简介: 用Java将ico格式转 PNG/JPG等格式

一. 什么是ico图标?
ico是一种图标格式,大量应用于网站,各个软件的logo或图标展示。

我们在进入某个网站或网页,它们上方标题左侧各自都带有logo图标。

这就是favicon.ico图标,它可以让浏览器的收藏夹中除显示相应的标题外,还可以用图标的方式区别不同的网站。

二. ico图标的特点
一张ico图标里,有可能只有一张或包含多张的图片信息,图片的清晰度越来越高。

三. 用Java来处理ico, 并转换成其他格式图片
做这种ico格式的图片转换功能,并不是特别容易,是有区别于普通图片格式转换,我经过不断尝试,调试,得到了一个自己还比较满意的结果。

我们在看代码之前,还是先看看我自己对这个功能的需求理解:

i. 需要有工具类能够读取ico的图片流。

ii. 对ico进行放大操作,尽可能地解决图片因为放大而出现模糊及毛刺。

iii. 能够将ico图片转换成其他格式的图片保存。

为了实现以上的3点功能,我需要借助这三个优秀的jar来实现此功能:

image4j.jar 主要读取ico图片
java-image-scaling-0.8.6.jar 主要缩放,修改图片大小
filters-2.0.235-1.jar 是image-scaling的依赖包
3.1 image4j.jar 主要读取ico图片
JDK没有提供读取ico图片的相关工具类,所以我们需要先解决读取ico格式的图片问题。

这里我找了相关的jar, 经过测试,image4j.jar中能读取。

image4j.jar中涉及的主要类:ICODecoder类

上面标记的四个方法中, 返回的是为什么是List集合?这里回到ICO的特点中来说,一张ICO图片包含一张或多张图片信息(取到图片后,看到图片主要是清晰度不同)
下面我是从发送http请求,从响应的图片流解析ICO图片

/**

 * 获取ICO图片
 * @param surl
 * @return
 */
public static List<ICOImage> getICOImageByUrl(String surl) {
    HttpURLConnection httpURLConnection = null;
    List<ICOImage> list = new ArrayList<>();
    try {
        URL url = new URL(surl);
            // https证书
            checkQuietly();
            httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setInstanceFollowRedirects(false);
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setConnectTimeout(30000);
            httpURLConnection.setReadTimeout(30000);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.setRequestProperty("Accept", "*/*");
            httpURLConnection.setRequestProperty("content-type","image/x-icon");
            // 创建连接
            httpURLConnection.connect();
            if (httpURLConnection.getResponseCode() == 200) {
                InputStream in = httpURLConnection.getInputStream();
                list = ICODecoder.readExt(in);  // 从响应结果集中获取ico图片流
                return list;
            }
    }catch (Exception e) {
        e.printStackTrace();
    }finally {
        if(httpURLConnection != null){
            httpURLConnection.disconnect();
        }
    }
    return list;
}

/**
//代码效果参考:http://www.zidongmutanji.com/bxxx/152148.html

  • 配置https证书
    */
    public static void checkQuietly() {

      try {
          HttpsURLConnection
                  .setDefaultHostnameVerifier(new HostnameVerifier() {
                      public boolean verify(String hostname,
                                            SSLSession session) {
                          return true;
                      }
                  });
          SSLContext context = SSLContext.getInstance("TLS");
          context.init(null, new X509TrustManager[] { new X509TrustManager() {
              public void checkClientTrusted(X509Certificate[] chain,
                                             String authType) throws CertificateException {
              }
    
              public void checkServerTrusted(X509Certificate[] chain,
                                             String authType) throws CertificateException {
              }
    
              public X509Certificate[] getAcceptedIssuers() {
                  return new X509Certificate[0];
              }
          } }, new SecureRandom());
          HttpsURLConnection.setDefaultSSLSocketFactory(context
                  .getSocketFactory());
      } catch (Exception e) {
          e.printStackTrace();
      }
    

    }
    //代码效果参考:http://www.zidongmutanji.com/bxxx/451200.html

3.2 java-image-scaling-0.8.6.jar 主要缩放,修改图片大小
由于ICO图标的像素大小(宽高)都比较小,再获取到图片后, 需要调整大小。如果采用普通方式去调整大小的话,图片会模糊,而且会出现类似马赛克的图像噪点。这样的效果并不理想。

下面的方法就是对ICO图片进行放大到80x80像素,在转换成PNG,并转换成base64,以便保存。

/**

 * 处理ICOImage图片
 */
public static String hadleICOImage(ICOImage icoImage) throws IOException {
    ResampleOp resampleOp = new ResampleOp(80,80);
    resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Oversharpened);
    BufferedImage bi = resampleOp.filter(icoImage.getImage(), null);
    BufferedImage result = null;
    /* 新生成结果图片 */
    result = new BufferedImage(80, 80,
            BufferedImage.TYPE_INT_RGB);
    Graphics2D g = result.createGraphics();
    g.setColor(Color.WHITE);
    g.drawImage(bi.getScaledInstance(80,80, Image.SCALE_SMOOTH), 0, 0, null);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(result, PNG, bos);
    BASE64Encoder encoder = new BASE64Encoder();
    return encoder.encode(bos.toByteArray()).replaceAll("\n", "").replaceAll("\r", "").trim();
}

3.2 实现ICO转PNG
从调用getICOImageByUrl()获取List这样一个list集合,获取最后一张,并实现转换。

List icoImages = getICOImageByUrl(url);
// 取最后一张最清晰的图片出来
ICOImage icoImage = icoImages.get(icoImages.size() - 1);
// 处理图片(转换大小,图片格式)并保存
hadleICOImage(icoImage);

相关文章
|
7月前
|
前端开发 JavaScript Java
Java中将图片转换为base64格式的技巧
这样,你就可以在Java中将图片转换为Base64格式了。这个方法的实现非常简单,只需要使用Java的内置库,无需任何额外的库。希望这个方法对你有所帮助。
470 22
|
12月前
|
Java
Java将OffsetDateTime格式化为 yyyy-MM-dd HH:mm:ss 如何写代码?
Java将OffsetDateTime格式化为 yyyy-MM-dd HH:mm:ss 如何写代码?
375 0
|
JSON 前端开发 Java
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
文章介绍了Java后端如何使用Spring Boot框架响应不同格式的数据给前端,包括返回静态页面、数据、HTML代码片段、JSON对象、设置状态码和响应的Header。
578 2
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
|
缓存 Java 数据处理
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
204 0
|
Java 编译器 开发者
Java演进问题之Truffle处理不同编程语言的源代码或中间格式如何解决
Java演进问题之Truffle处理不同编程语言的源代码或中间格式如何解决
122 2
使用java文件过滤器输出制定格式文件路径
使用java文件过滤器输出制定格式文件路径
|
Java C语言
Java微信语音amr格式转mp3格式
Java微信语音amr格式转mp3格式
|
Java
JAVA读取EMF文件并转化为PNG,JPG,GIF格式
JAVA读取EMF文件并转化为PNG,JPG,GIF格式
723 0
|
存储 Java 索引
Java的基本语法格式详解
Java的基本语法格式详解
390 0
下一篇
oss云网关配置