java - 编写 ico 文件 java

标签 java ico

最近我对用 java 创建 .ico 文件或 Windows 图标文件产生了兴趣。这是我使用的当前代码。我从这里获得了文件格式规范 http://en.wikipedia.org/wiki/ICO_%28file_format%29

    BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
    Graphics g = img.getGraphics();
    g.setColor(Color.GREEN);
    g.fillRect(0, 0, 16, 16);
    byte[] imgBytes = getImgBytes(img);
    int fileSize = imgBytes.length + 22;
    ByteBuffer bytes = ByteBuffer.allocate(fileSize);
    bytes.order(ByteOrder.LITTLE_ENDIAN);
    bytes.putShort((short) 0);//Reserved must be 0
    bytes.putShort((short) 1);//Image type
    bytes.putShort((short) 1);//Number of image in file
    bytes.put((byte) img.getWidth());//image width
    bytes.put((byte) img.getHeight());//image height
    bytes.put((byte) 0);//number of colors in color palette
    bytes.put((byte) 0);//reserved must be 0
    bytes.putShort((short) 0);//color planes
    bytes.putShort((short) 0);//bits per pixel
    bytes.putInt(imgBytes.length);//image size
    bytes.putInt(22);//image offset
    bytes.put(imgBytes);
    byte[] result = bytes.array();
    FileOutputStream fos = new FileOutputStream("C://Users//Owner//Desktop//picture.ico");
    fos.write(result);
    fos.close();
    fos.flush();

private static byte[] getImgBytes(BufferedImage img) throws IOException
{
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(img, "png", bos);
    return bos.toByteArray();
}

问题是 Windows 似乎无法打开图像,当我尝试使用 Windows 照片库打开图像时出现错误。但是,当我尝试使用 gimp 打开图像时,图像可以正常打开。我究竟做错了什么。我觉得我在文件头中弄乱了一些东西。编辑:在桌面上甚至陌生人图片看起来是正确的,只是当我尝试打开它时不正确。

在我的桌面上,图像看起来像这样 enter image description here

当我尝试在 Windows 照片库中打开它时,它显示此错误

enter image description here

在 png 尝试失败后,我尝试使用位图图像代替,这是我的新代码

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

import javax.imageio.ImageIO;

public class IconWriter
{
    public static void main(String[] args) throws HeadlessException, AWTException, IOException
    {
        BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
        Graphics g = img.getGraphics();
        g.setColor(Color.GREEN);
        g.fillRect(0, 0, 16, 16);
        byte[] imgBytes = getImgBytes(img);
        int fileSize = imgBytes.length + 22;
        ByteBuffer bytes = ByteBuffer.allocate(fileSize);
        bytes.order(ByteOrder.LITTLE_ENDIAN);
        bytes.putShort((short) 0);//Reserved must be 0
        bytes.putShort((short) 1);//Image type
        bytes.putShort((short) 1);//Number of images in file
        bytes.put((byte) img.getWidth());//image width
        bytes.put((byte) img.getHeight());//image height
        bytes.put((byte) 0);//number of colors in color palette
        bytes.put((byte) 0);//reserved must be 0
        bytes.putShort((short) 0);//color planes
        bytes.putShort((short) 0);//bits per pixel
        bytes.putInt(imgBytes.length);//image size
        bytes.putInt(22);//image offset
        bytes.put(imgBytes);
        byte[] result = bytes.array();
        FileOutputStream fos = new FileOutputStream("C://Users//Owner//Desktop//hi.ico");
        fos.write(result);
        fos.close();
        fos.flush();
    }

    private static byte[] getImgBytes(BufferedImage img) throws IOException
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(img, "bmp", bos);
        byte[] bytes = bos.toByteArray();
        return Arrays.copyOfRange(bytes, 14, bytes.length);
    }
}

现在,当我尝试在照片库中打开我的图像时,图像看起来像这样我不知道为什么它现在不起作用,尤其是为什么会出现奇怪的线条,尽管我怀疑它与颜色平面属性有关在 ico 图片标题中。 enter image description here

最佳答案

奇怪……但是:让BMP图片比想要的图标高两倍。 ICO header中声明的icon size和之前一样保持不变,只是图片要高一些。然后将区域 (0,0)-(16,16) 保持为黑色(它定义了透明度,但我不知道它是如何编码的,全黑用于不透明作品)。在BufferedImage中的(0,16)-(16,32)区域绘制需要的内容。换句话说,将高度的一半添加到所有像素坐标。

请注意,Windows 桌面可能会缓存图标并拒绝在桌面上更新它们。如果有疑问,请通过另一个资源管理器窗口打开桌面文件夹并在那里执行“更新”。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

import javax.imageio.ImageIO;

public class IconWriter
{
    public static void main(String[] args) throws IOException
    {
      // note the double height
        BufferedImage img = new BufferedImage(16, 32, BufferedImage.TYPE_INT_RGB);
        Graphics g = img.getGraphics();
        g.setColor(Color.GREEN);
        g.fillRect(0, 16, 16, 16);// added 16 to y coordinate
        byte[] imgBytes = getImgBytes(img);
        int fileSize = imgBytes.length + 22;
        ByteBuffer bytes = ByteBuffer.allocate(fileSize);
        bytes.order(ByteOrder.LITTLE_ENDIAN);
        bytes.putShort((short) 0);//Reserved must be 0
        bytes.putShort((short) 1);//Image type
        bytes.putShort((short) 1);//Number of images in file
        bytes.put((byte) img.getWidth());//image width
        bytes.put((byte) (img.getHeight()>>1));//image height, half the BMP height
        bytes.put((byte) 0);//number of colors in color palette
        bytes.put((byte) 0);//reserved must be 0
        bytes.putShort((short) 0);//color planes
        bytes.putShort((short) 0);//bits per pixel
        bytes.putInt(imgBytes.length);//image size
        bytes.putInt(22);//image offset
        bytes.put(imgBytes);
        byte[] result = bytes.array();
        FileOutputStream fos = new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\hi.ico");
        fos.write(result);
        fos.close();
        fos.flush();
    }

    private static byte[] getImgBytes(BufferedImage img) throws IOException
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(img, "bmp", bos);
        byte[] bytes = bos.toByteArray();
        return Arrays.copyOfRange(bytes, 14, bytes.length);
    }
}

关于java - 编写 ico 文件 java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18521470/

相关文章:

resources - 从命令行向现有 EXE 文件添加图标

java - 从命令行生成 SVG 失败,但使用 NetBeans 生成成功

java - overridePendingTransition 用于平滑地滑入和滑出 Activity

java - 为什么我应该在 java 中使用 (String[])null 而不是 null?

java - 如果我在异常上调用 getCause(),为什么我必须处理 Throwable

optimization - 支持 .ico 文件中的嵌入式 PNG 作为浏览器中的图标

image - JavaFX 2.2 图像支持 .ico?

java - 我的 Java 程序没有改变变量的值

html - Ico 不会显示在选项卡上

powershell - 图标损坏与Powershell exe到ico转换器