如果我们要建立自己的网站,网站的favicon是必不可少的,但是我们日常常见的图片通常是pngjpg等格式,所以这时候就需要对图片进行转化,采用本程序可以非常简单的将pngjpg等常见的图片格式转为ico格式

生成16x1632x32尺寸的图片

以下代码主要是使用了image4j这个第三方库,网上也有一些在线的网页可以转化,这点看自己需求。

下面的代码只需要修改输入图片地址以及文件输出地址,即可获得想要的16x1632x32或其他尺寸的ico图片

注意ico在网页中的引用格式为

<head>
    <link rel="shortcut icon" href="/assets/images/favicon/maple32.ico">
</head>

1. Gradle引入依赖

// https://mvnrepository.com/artifact/org.jclarion/image4j
implementation group: 'org.jclarion', name: 'image4j', version: '0.7'

2. 实现代码

package com.flywinter;

import net.sf.image4j.codec.ico.ICOEncoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * Created by IntelliJ IDEA
 * User:Zhang Xingkun
 * Date:2022/4/22 22:41
 * Description: This code can convert png jpeg jeg and so on to ico which size can be 16x16px,32x32px or other square size
 */
public class IcoTransform {
    public static void main(String[] args) throws IOException {

        final var sourcePath = "E:\\study\\Code\\Demo\\maple.png";

        final var image = getSquareBufferedImage(sourcePath);

        final var copyBufferImage = copyBufferImage(image);

        get16x16Ico(image, "E:\\study\\Code\\Demo\\maple16.ico");
        get32x32Ico(copyBufferImage, "E:\\study\\Code\\Demo\\maple32.ico");

    }

    private static BufferedImage getSquareBufferedImage(String sourcePath) throws IOException {
        var image = ImageIO.read(new File(sourcePath));
        final var originWidth = image.getWidth();
        final var originHeight = image.getHeight();
        if (originHeight > originWidth) {
            image = image.getSubimage(0, (int) ((originHeight - originWidth) / 2.0), originWidth, originWidth);
        }
        if (originHeight < originWidth) {
            image = image.getSubimage((int) ((originWidth - originHeight) / 2.0), 0, originHeight, originHeight);
        }
        return image;
    }

    private static void get16x16Ico(BufferedImage image, String path) throws IOException {
        final var finalSize = 16;
        saveSquareIco(image, finalSize, path);
    }

    private static void get32x32Ico(BufferedImage image, String path) throws IOException {
        final var finalSize = 32;
        saveSquareIco(image, finalSize, path);
    }

    /**
     *
     * @param image source
     * @param finalSize ico size
     * @param path  output path
     * @throws IOException
     */
    private static void saveSquareIco(BufferedImage image, int finalSize, String path) throws IOException {
        final var scaledInstance = image.getScaledInstance(finalSize, finalSize, Image.SCALE_SMOOTH);
        final var bufferedImage = new BufferedImage(finalSize, finalSize, BufferedImage.TYPE_INT_RGB);
        final var graphics = bufferedImage.createGraphics();
        graphics.drawImage(scaledInstance, 0, 0, null);
        graphics.dispose();
        ICOEncoder.write(bufferedImage, new File(path));
    }

    /**
     * copy BufferedImage
     *
     * @param source BufferedImage
     * @return BufferedImage
     */
    private static BufferedImage copyBufferImage(BufferedImage source) {
        BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
        Graphics g = b.getGraphics();
        g.drawImage(source, 0, 0, null);
        g.dispose();
        return b;
    }

}

3.注意事项

  • 关于上述代码,sourcePath为原始图片文件的路径,运行该程序后,会自动在对应目录生成16x16以及32x32尺寸大小的ico图片。

  • 由于生成的图片为正方形,所以如果输入的图片为长方形,会以图片的短边为正方形的边长,从图片的中间进行截取,这点要注意。

  • 上述转换ico图片的代码实际上只有一行而已,其他的代码基本上都是为了将输入的图片进行方形处理,缩放图片大小等,由于缩放为等比缩放,所以原始图片内容不要太复杂,否则缩放后的图像将会很难看。毕竟是将一个大尺寸的图片进行缩放,肯定会丢失掉很多细节。