最近我已经变得有兴趣在 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,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照片库打开图像时出现错误.但是,当我尝试使用gimp打开图像时,图像打开正常.我究竟做错了什么.我觉得我正在搞乱文件头中的东西.编辑:即使陌生人在桌面上的图片看起来正确,只是不是当我尝试打开它.

在我的桌面上,图像看起来像这样

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

在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,BufferedImage.TYPE_INT_RGB);
        Graphics g = img.getGraphics();
        g.setColor(Color.GREEN);
        g.fillRect(0,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图像标题.

解决方法

其实,你所提到的问题是在规范(维基百科)中提到的.
引用:

Images with less than 32 bits of color depth[6] follow a particular
format: the image is encoded as a single image consisting of a color
mask (the “XOR mask”) together with an opacity mask (the “AND mask”).

这很复杂

创建32位图像 – >失败

所以,上面的引用可能会让你想到:“哦,我只需要使32位而不是24位”,作为一种解决方法.不幸的是,这不行.那么实际上存在一个32位的BMP格式.但是最后8位没有真正使用,因为BMP文件并不真正支持透明度.

所以,您可以尝试使用不同的图像类型:INT_ARGB_PRE,它使用32位颜色深度.但是,一旦您尝试使用ImageIO类保存它,您会注意到没有任何反应.流的内容将为空.

BufferedImage img = new BufferedImage(16,BufferedImage.TYPE_INT_ARGB_PRE);
ImageIO.write(img,bos);

替代解决方案:image4j

ImageIO无法处理32位图像,但还有其他的图库可以做到这一点. image4J库可以保存32位bmp文件.但是我猜测是因为某些原因你不想使用这个库. (使用image4J会使您的大部分代码无意义,因为image4jhas内置ICO创建支持).

第二个选项:创建一个移动的24位图像 – >作品

所以,让我们再来看一下维基百科说什么,32位BMP数据.

The height for the image in the ICONDIRENTRY structure of the ICO/CUR
file takes on that of the intended image dimensions
(after the masks
are composited),whereas the height in the BMP header takes on that
of the two mask images combined (before they are composited).
Therefore,the masks must each be of the same dimensions,
and the height specified in the BMP header must be exactly twice the
height specified in the ICONDIRENTRY structure
.

所以,第二个解决方案是创建一个原始大小的两倍的图像.而实际上你只需要替换你的getimageBytes函数,下面的代码就可以了.如上所述,代码的另一部分中指定的ICONDIRENTRY标题保持原始图像高度.

private static byte[] getImgBytes(BufferedImage img) throws IOException
  {
    // create a new image,with 2x the original height.
    BufferedImage img2 = new BufferedImage(img.getWidth(),img.getHeight()*2,BufferedImage.TYPE_INT_RGB);

    // copy paste the pixels,but move them half the height.
    Raster sourceRaster = img.getRaster();
    WritableRaster destinationRaster = img2.getRaster();
    destinationRaster.setRect(0,img.getHeight(),sourceRaster);

    // save the new image to BMP format. 
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(img2,bos);

    // strip the first 14 bytes (contains the bitmap-file-header)
    // the next 40 bytes contains the DIB header which we still need.
    // the pixel data follows until the end of the file.
    byte[] bytes = bos.toByteArray();
    return Arrays.copyOfRange(bytes,bytes.length);
  }

我建议使用标题如下:

ByteBuffer bytes = ByteBuffer.allocate(fileSize);
bytes.order(ByteOrder.LITTLE_ENDIAN);

bytes.putShort((short) 0);
bytes.putShort((short) 1);
bytes.putShort((short) 1);
bytes.put((byte) img.getWidth());
bytes.put((byte) img.getHeight()); //no need to multiply
bytes.put((byte) img.getColorModel().getNumColorComponents()); //the pallet size
bytes.put((byte) 0);
bytes.putShort((short) 1); //should be 1
bytes.putShort((short) img.getColorModel().getPixelSize()); //bits per pixel
bytes.putInt(imgBytes.length);
bytes.putInt(22);
bytes.put(imgBytes);

写ico文件java的更多相关文章

  1. swift 下 UNcode字符串 转为中文字符

    顺便一提,1F436这个16进制数,也能直接通过UnicodeScalar转换成字符串,就像下面这样DOGFACE

  2. Swift学习第十三枪-使用Swift开发IOS中蓝牙4.0的开发流程

    前面总结了几篇关于Swift的使用,今天要讲的是关于使用Swift开发IOS中蓝牙4.0的开发流程,我以前只是会搞android的蓝牙开发,最近开始了Swift的学习,作为一个swift爱好者,想把蓝牙4.0的这个装逼神器在swift中使用一下。使用Swift开发IOS中蓝牙4.0的开发流程有如下的几个步骤:建立桥接文件案例的实现1.建立桥接文件1.1在用Swift使用OC中得类文件的时候,需要进行桥接,首先建一个.h的头文件。

  3. 往返Swift数字类型到/从数据

    Swift3倾向于Data而不是[UInt8],我试图找出最有效/惯用的编码/解码方式,将各种数字类型转换为Data对象。有thisanswerforusing[UInt8],但似乎使用各种指针API,我不能在数据上找到。在早期的Swift版本中,你可以通过做函数参数本身是一个变量,这不再支持了。>最后声明符合所有类型,可以安全地转换为数据并返回:这使得转换更加优雅:第二种方法的优点是,您不能无意中执行不安全的转化。缺点是你必须显式列出所有“安全”类型。

  4. 在Swift中将两个字节的UInt8数组转换为UInt16

    使用Swift我想将字节从uint8_t数组转换为整数。“C”示例:Swift尝试:从Swift中的UInt8数组创建UInt16值的正确语法或代码是什么?我对NSData版本感兴趣,并且正在寻找一个不使用临时数组的解决方案。如果你想通过NSData去,那么它将像这样工作:或者:两种变体都假定字节是主机字节顺序。

  5. 如何在swift中将Int16转换为两个UInt8字节

    我有一些二进制数据,将两个字节的值编码为有符号整数.解码这很简单–我可以从这些字节中提取Int16值:编码这是我遇到问题的地方.我的大多数数据规范都要求使用UInt,这很简单,但我无法提取组成Int16的两个字节题如何提取构成Int16值的两个字节你应该使用无符号整数:如果您想将UInt16转换为等效的Int16,那么您可以使用特定的初始化程序:反之亦然:在你的情况下:

  6. Swift 3中的数据MD5

    我正在尝试获取我的数据的MD5哈希值.不幸的是,我已经将框架升级到swift3,而我一直使用的方法现在不起作用.我已经转换了大部分内容,但我无法从数据中获取字节数:CommonCrypto已作为自定义模块导入.问题是我得到’字节’不可用:在CC_MD5上使用withUnsafeBytes(data.bytes,…

  7. 使用Swift从NSData获取数据

    2)文档说这个参数应该是_buffer:UnsafeMutablePointer.那么这是如何工作的呢?为什么我要这样做而不是更原生/托管[Uint8]构造?我想知道UnsafeMutablePointer是否是一个协议,但它是一个结构.大胆地直接读取值,我想也许我可以尝试另一种结构.我有一个6字节的结构,看起来像:哪个实际上有效!但这让我担心结构包装细节?

  8. 如何在Swift中创建打包数据结构?

    我正在将一个项目从Objective-C转换为Swift,我正在使用一个打包的结构来输入通过套接字发送的转换二进制消息:我不确定Swift中最好的方法是什么,我能得到的最接近的近似值是:翻译中丢失了两个重要的细节:没有保证整数类型的比特,并且没有结构打包.我不认为这可以在Swift中表达,但如果是这样,怎么样?

  9. 如何解码base64字符串并将其转换为pdf / jpg并将其保存在存储中

    谢谢大家=)解决方法你可以试试这个:哪里:>filepath:新文件的路径>base64String:您要转换的base64字符串

  10. android / java中的校验和计算

    我在android/java中写了一个校验和计算函数.功能如下计算校验和的输入值为0xEF,0x01,0xEF,0x33,0x0C,0xB8,0xE5,0xFC,0x34,0xFF,0xFF.我手动计算校验和值,结果为0xCE4.当使用上面的函数时,我的答案为0xFFFFFFE4.在我的计算中是否有任何错误,如果是,那么请纠正我.谢谢解决方法字节根据JavaDocs:Thevalueofabyte

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部