【问题标题】:How to change the image type of a BufferedImage which is loaded from file?如何更改从文件加载的 BufferedImage 的图像类型?
【发布时间】:2014-12-13 09:45:33
【问题描述】:

我正在尝试访问使用ImageIO.read(filePath) 从文件加载的BufferedImage 中的像素,但我得到此错误

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)

在代码中,错误所在的行在构造函数中,如下所示:

// Get the pixel array from the BufferedImage
this.pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

据我了解,BufferedImage 不是BufferedImage.TYPE_INT_RGBBufferedImage.TYPE_INT_ARGB 类型。因为我在游戏的其余部分使用这些类型,所以我想知道是否有办法将加载的图像从加载的类型“转换”为另一种类型。
就我而言,我想将图像类型转换为BufferedImage.TYPE_INT_ARGB

【问题讨论】:

    标签: java type-conversion bufferedimage javax.imageio


    【解决方案1】:

    用你想要的类型创建一个新的缓冲图像

    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();
    

    【讨论】:

    • 好的,谢谢!但是您也必须在新图像上绘制旧图像。
    • 我会将其添加到您的答案中。
    • 修复代码只调用一次createGraphics()getGraphics() 调用相同)。
    【解决方案2】:

    稍微(好吧,我承认,相当多)冗长,但在大多数情况下更快且内存效率更高的方法是将图像直接加载到TYPE_INT_ARGB 图像中。

    如果你的图片很大,你会从这样做中受益很多,而不是首先加载到byte 类型。如果您的图像很小,则可能不值得额外的代码复杂性,因为您几乎不会注意到差异。

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

    // 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();
    }
    

    【讨论】:

    • 谢谢!我的图像非常小(大约 32x32 像素),所以我不会使用此代码,但我会支持它。 /TheDDestroyer12
    • 非常感谢!但是,对于 jpeg 图像,setDestinationType 不起作用(使用集成的 ICC 配置文件)。 param.setDestination(new BufferedImage(reader.getWidth(0), reader.getHeight(0), BufferedImage.TYPE_INT_ARGB));做这项工作;-)
    【解决方案3】:

    您是在告诉 JVM image.getRaster().getDataBuffer() 在实际返回 DataBufferByte 时返回 DataBufferInt。那是一个 ClassCastException。您需要将返回值转换为正确的类型。

    // Get the pixel array from the BufferedImage
    this.pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    

    【讨论】:

    • 是的,但是如果您阅读了整个问题,您会看到我提到我不希望图像属于 BufferedImage.TYPE_INT_ARGB 类型,因为我所有的其他 BufferedImages 都是那种类型,我按照@overflowed的建议解决了这个问题。无论如何,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-10-27
    • 2020-08-15
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 2015-10-09
    相关资源
    最近更新 更多