Java 如何更改从文件加载的BuffereImage的图像类型?

Java 如何更改从文件加载的BuffereImage的图像类型?,java,type-conversion,bufferedimage,javax.imageio,Java,Type Conversion,Bufferedimage,Javax.imageio,我试图访问使用ImageIO.read(filePath)从文件加载的buffereImage中的像素,但我发现此错误: Exception in thread "Game" java.lang.ClassCastException: java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt at com.package.graphics.Texture.<init>(Textur

我试图访问使用
ImageIO.read(filePath)
从文件加载的
buffereImage
中的像素,但我发现此错误

Exception in thread "Game" java.lang.ClassCastException: java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt
    at com.package.graphics.Texture.<init>(Texture.java:29)
    at com.package.graphics.Texture.loadTexture(Texture.java:40)
    at com.package.Game.run(Game.java:71)
    at java.lang.Thread.run(Unknown Source)
据我所知,BuffereImage的类型不是
BuffereImage.type\u INT\u RGB
BuffereImage.type\u INT\u ARGB
。由于我在游戏的其余部分使用这些类型,我想知道是否有办法将加载的图像从加载时的类型“转换”为另一种类型。

在我的例子中,我想将映像类型转换为
缓冲映像。键入\u INT\u ARGB

用您想要的类型创建一个新的缓冲映像

BufferedImage in = ImageIO.read(img);
BufferedImage newImage = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_INT_ARGB);

Graphics2D g = newImage.createGraphics();
g.drawImage(in, 0, 0, in.getWidth(), in.getHeight(), null);
g.dispose();

您告诉JVM,
image.getRaster().getDataBuffer()
在实际返回DataBufferByte时返回DataBufferInt。这是一个阶级例外。您需要将返回值强制转换为正确的类型

// Get the pixel array from the BufferedImage
this.pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
一种稍微(好的,我承认,有点)详细,但在大多数情况下更快、内存效率更高的方法是将图像直接加载到
TYPE_INT_ARGB
图像中

如果您的图像很大,那么通过这种方式,您将从中受益匪浅,首先将其加载到
字节
类型中。如果您的图像很小,可能不值得额外的代码复杂性,因为您几乎不会注意到其中的差异

无论如何,您可以这样做:

// Get the pixel array from the BufferedImage
this.pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
// Create input stream
ImageInputStream input = ImageIO.createImageInputStream(file);

try {
    // Get the reader
    Iterator<ImageReader> readers = ImageIO.getImageReaders(input);

    if (!readers.hasNext()) {
        throw new IllegalArgumentException("No reader for: " + file); // Or simply return null
    }

    ImageReader reader = readers.next();

    try {
        // Set input
        reader.setInput(input);

        // Configure the param to use the destination type you want
        ImageReadParam param = reader.getDefaultReadParam();
        param.setDestinationType(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB));

        // Finally read the image, using settings from param
        BufferedImage image = reader.read(0, param);
    }
    finally {
        // Dispose reader in finally block to avoid memory leaks
        reader.dispose();
    }
}
finally {
    // Close stream in finally block to avoid resource leaks
    input.close();
}
//创建输入流
ImageInputStream输入=ImageIO.createImageInputStream(文件);
试一试{
//吸引读者
迭代器读卡器=ImageIO.getImageReaders(输入);
如果(!readers.hasNext()){
抛出新的IllegalArgumentException(“没有读卡器:”+文件);//或者简单地返回null
}
ImageReader=readers.next();
试一试{
//设置输入
reader.setInput(输入);
//配置参数以使用所需的目标类型
ImageReadParam param=reader.getDefaultReadParam();
参数setDestinationType(ImageTypeSpecifier.CreateFromBuffereImage类型(BuffereImage.TYPE_INT_ARGB));
//最后,使用param中的设置读取图像
BuffereImage image=reader.read(0,参数);
}
最后{
//在finally块中处理读卡器以避免内存泄漏
reader.dispose();
}
}
最后{
//关闭finally块中的流以避免资源泄漏
input.close();
}

好的,谢谢!但是你也必须在新的图像上绘制旧的图像。我会将其添加到你的答案中。修复了代码,使其只调用
createGraphics()
一次(
getGraphics()
调用相同的图像)。是的,但是如果你阅读了整个问题,你会看到我提到的图像类型不是
BufferedImage.type\u INT\u ARGB
,因为我的所有其他
BufferedImage
s都属于这种类型,我按照@overflow的建议解决了这个问题。谢谢你,谢谢!我的图像非常小(大约32x32像素),所以我不会使用这段代码,但我会更新它/毁灭者12非常感谢!但是,对于jpeg图像,setDestinationType不起作用(使用集成的ICC配置文件)。参数setDestination(新的BuffereImage(reader.getWidth(0)、reader.getHeight(0)、BuffereImage.TYPE_INT_ARGB));做这项工作;-)