我正在尝试用Java编写ICO解码器,因此我能够显示来自网站的favicon。我第一次使用image4j库,但发现它没有解码我扔给它的所有favicon。因此经过一些调查后,我意识到image4j只能解码包含PNG图像的ICO文件或标题大小为40 which turns out to be bitmaps with the header type BITMAPINFOHEADER
的BMP图像。由于Windows Vista大多数位图包含BITMAPV5HEADER
或其他类似BITMAPV4HEADER
的内容,因此image4j不适合我。
我尝试编写自己的ICO解码器,现在可以正常工作,但唯一的问题是从数据中重新构造BufferedImage
。根据维基百科,PNG图像完全存储在其中,并且BMP图像也完全存储在其中但没有文件头。而不是为每个压缩,图像格式编写解码例程......我注意到ImageIO API支持大多数Windows位图标题(8位,16位位图和Adobe除外)。但是有一个小问题,为了使用ImageIO.read(Inputstream input),BMP图像需要一个可以看到here的文件头。所以我要做的是为BMP图像重新创建the file header,从ICO文件追加BMP数据并尝试使用ImageIO.read(Inputstream stream)读取它。目前我得到一个EOF异常,我认为它必须在文件头中声明图像数据偏移,但也可能是我写错了数据。
下面是一些显示我正在做的事情的代码:
final BitmapInfoHeader infoHeader = new BitmapInfoHeader(data);//decodes bitmapheader to figure out amount of color palette entries
final int fileHeaderSize = 14;
final int offset = fileHeaderSize + infoHeader.headerSize + infoHeader.clrImportant * 4;// offset = 54
final int fileSize = offset + data.length + fileHeaderSize;// file size = 1196
final ByteBuffer BMPFile = ByteBuffer.allocate(fileSize).order(ByteOrder.LITTLE_ENDIAN);
//BMPFile.putChar('B');//when doing this file header is 16 bytes long
//BMPFile.putChar('M');
BMPFile.put((byte) 'B');//when doing this file header is 14 bytes long
BMPFile.put((byte) 'M');
BMPFile.putInt(fileSize);
BMPFile.putInt(0); //Reserved
BMPFile.putInt(offset);
BMPFile.put(data); //Data from ICO file
final byte[] imageData = BMPFile.array();
System.out.println("File header + data: " + Arrays.toString(imageData));
final BufferedImage favIcon = ImageIO.read(new ByteArrayInputStream(imageData));//Throws EOF exception
输出:
/ *******阅读ICO文件******* /
图片类型:1 - > .ICO
参赛作品数量:2
条目#1-> 16X16 |调色板:0 |保留:0 |飞机:0 |格式:32 | 数据大小:1128 |数据偏移:38
条目#2-> 32X32 |调色板:0 |保留:0 |飞机:0 |格式:32 | 数据大小:4264 |数据偏移:1166
数据输入#1:(1128) - > [40,0,0,0,16,0,0,0,32,0,0,0,1,0, 32,0,0,0,0,0,64,4 ......
/ *******阅读BITMAP HEADER ******* /
HeaderSize:40
[BITMAPINFOHEADER]
宽度:16 |身高:32 | colorPlanes:1 | bitsPerPixel:32 |压缩:0 |图像大小:1088 | xPelsPerMeter:0 | yPelsPerMeter:0 | clrUsed:0 | clrImportant:0/ *******创建BITMAP文件标题******* /
文件头+数据:[66,77,0,0,4,-84,0,0,0,0,0,0,04, 40,0,0,0,16,0,0,0,32,0,0,0,1,0,32,0,0,0,0,0,64, 4,...
当使用字节表示幻数时重新构造文件头时,文件头大小为14个字节:
BMPFile.put((byte) 'B');
BMPFile.put((byte) 'M');
"B" "M" | 14 bytes
文件头+数据:[66,77,0,0,4,-84,0,0,0,0,0,0,04, 40,0,0,0,16,0,0,0,32,0,0,0,1,0,32,0,0,0,0,0,64, 4,...
但是当使用putChar作为幻数时,文件头大小为16字节:
BMPFile.putChar('B');
BMPFile.putChar('M');
--B-- --M-- | 16 bytes
文件头+数据:[0,66,0,77,0,0,4,-84,0,0,0,0,0,0,04,50,0,0,0, 16,0,0,0,32,0,0,0,1,0,32,0,0,0,0,0,64,4,
欢迎所有帮助:)