写ico文件java
最近我已经变得有兴趣在
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图像标题. 解决方法
其实,你所提到的问题是在规范(维基百科)中提到的.
引用:
这很复杂 创建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数据.
所以,第二个解决方案是创建一个原始大小的两倍的图像.而实际上你只需要替换你的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); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |