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);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM