用Java读取.ICO文件

时间:2015-08-13 14:47:54

标签: java bitmap byte ico

我正在尝试加载ICO文件,但我似乎在图像数据大小和图像数据偏移值中得到奇怪的值,导致ArrayOutOfBoundsException。任何帮助表示赞赏。我试过Little / Big endian但没有成功。我找到了ICO结构的信息here

代码:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

public class IcoFileReader {

    public static void main(String[] args) {
        URL url = null;
        try {
            url = new URL("https://www.google.be/favicon.ico");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        if(url == null) {
            System.err.println("Url is null");
            System.exit(-1);
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try {
            final byte[] chunk = new byte[4096];
            final InputStream stream = url.openStream();
            int bytesRead;

            while ((bytesRead = stream.read(chunk)) > 0) {
                outputStream.write(chunk, 0, bytesRead);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        final byte[] icoBytes = outputStream.toByteArray();
        System.out.println("Ico bytes: " + Arrays.toString(icoBytes));

        System.out.println("-- HEADER --");
        System.out.println("Reserved: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 0, 2)));
        System.out.println("Image type: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 2, 4)));
        System.out.println("Num images: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 4, 6)));
        System.out.println("");
        System.out.println("-- BODY --");
        System.out.println("Width: " + icoBytes[6]);
        System.out.println("Height: " + icoBytes[7]);
        System.out.println("Color Palette: " + icoBytes[8]);
        System.out.println("Reserved: " + icoBytes[9]);
        System.out.println("Color planes: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 10, 11)));
        System.out.println("Bits per pixel: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 12, 13)));
        System.out.println("Img data size: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 13, 17)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 13, 17)).order(ByteOrder.LITTLE_ENDIAN).getInt());
        System.out.println("Offset beginning data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 17, 21)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 17, 21)).order(ByteOrder.LITTLE_ENDIAN).getInt());

        final int imgSize = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 13, 17)).order(ByteOrder.LITTLE_ENDIAN).getInt();
        final int offset = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 17, 21)).order(ByteOrder.LITTLE_ENDIAN).getInt();
        System.out.println("Bytes length: " + icoBytes.length);
        System.out.println("Image data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, offset, offset + imgSize)));
       /* for(int i = 0; i < icoBytes[4]; i ++) {
            final int start = (i * offset);
            System.out.println("Image data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, start, start + imgSize)));
        }*/
    }
}

输出:

- HEADER -

保留:[0,0]

图片类型:[1,0]

Num图片:[2,0]

- BODY -

宽度:16

身高:16

调色板:0

保留:0

颜色平面:1

每像素位数:[32]

Img数据大小:[0,104,4,0] - 288768

偏移开始数据:[0,38,0,0] - 9728

字节长度:5430

线程“main”中的异常java.lang.ArrayIndexOutOfBoundsException

1 个答案:

答案 0 :(得分:0)

你被绊倒了。

System.out.println("Color planes: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 10, 12)));
System.out.println("Bits per pixel: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 12, 14)));
System.out.println("Img data size: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 14, 18)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 14, 18)).order(ByteOrder.LITTLE_ENDIAN).getInt());
System.out.println("Offset beginning data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 18, 22)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 18, 22)).order(ByteOrder.LITTLE_ENDIAN).getInt());

final int imgSize = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 14, 18)).order(ByteOrder.LITTLE_ENDIAN).getInt();
final int offset = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 18, 22)).order(ByteOrder.LITTLE_ENDIAN).getInt();

(使用ByteBuffer可以在没有显式索引的情况下允许顺序读取;并且只设置字节顺序一次。)