原创 | 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;
    }
/**
* 配置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();
        }
    }

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<ICOImage>这样一个list集合,获取最后一张,并实现转换。

List<ICOImage>  icoImages = getICOImageByUrl(url);
// 取最后一张最清晰的图片出来
ICOImage icoImage = icoImages.get(icoImages.size() - 1);
// 处理图片(转换大小,图片格式)并保存
hadleICOImage(icoImage);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容

  • 三月初三是妈妈的生日,我早早给她和爸爸精心挑选了春天的衣服、鞋子,还有妈妈爱吃的小点心,还把在春节期间给她们照的各...
    云儿飘过阅读 2,569评论 97 64
  • 官渡之战是历史中最大的三个大战中的之一,也是第一个以弱胜强的战争,而在三国里面是最先一个战役,而曹胜袁败。 先是因...
    放下callmingman阅读 1,292评论 0 0
  • 看青青的小草、绿绿的树林树林像一把把大伞! 蓝蓝的天空,无边无际啊!温暖的阳光。好像春天一样,多美呀!走啊走,看见...
    兰博_aea2阅读 132评论 0 1
  • 日子当真是匆匆而过,仿佛就是一瞬间,2017年跟我们说再见了。 这一年,我怕了, 因为年龄越大,离开的亲人就越多,...
    蓝朵格格阅读 358评论 0 3
  • 瑞雪染山川,石壁焕新颜。 冬至江水碧,画里游船欢。
    三峡孬张阅读 272评论 0 6