【问题标题】:Loading the pixels of a scaled BufferedImage加载缩放的 BufferedImage 的像素
【发布时间】:2014-02-03 17:03:56
【问题描述】:

我正在尝试将图像缩放到不同的宽度和高度。然后从缩放图像的像素创建一个像素阵列。问题是我得到一个错误。

 java.lang.ClassCastException: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage    

我可以通过什么方式获得新尺寸图像的像素?

代码如下:

protected void scaleImage(int newWidth, int newHeight) {
    try {

        BufferedImage image = (BufferedImage) img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);

        width = newWidth;
        height = newHeight;
        scaledWidth = newWidth;
        scaledHeight = newHeight;
        //re init the pixels
        pixels = new int[scaledWidth * scaledHeight];

        ((BufferedImage) image).getRGB(0, 0, scaledWidth, scaledHeight, pixels, 0, scaledWidth);
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(0);
    }
}

【问题讨论】:

    标签: bufferedimage pixels


    【解决方案1】:

    您遇到的问题是image.getScaledInstance(...) 返回一个图像,无论imageImage 还是BufferedImage

    现在,出于这个原因(以及其他原因,主要与性能相关),不建议使用image.getScaledImage(...)。例如,请参阅 The Perils of Image.getScaledInstance() 了解更多信息,以及一些替代的缩放方法。

    改编自您的代码,您可以使用:

    int newWidth, int newHeight; // from method parameters
    
    BufferedImage image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = image.createGraphics();
    
    try {
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(img, 0, 0, newWidth, newHeight, null);
    }
    finally {
        g.dispose();
    }
    
    scaledWidth = newWidth;
    scaledHeight = newHeight;
    
    //re init the pixels
    pixels = new int[scaledWidth * scaledHeight];
    image.getRGB(0, 0, scaledWidth, scaledHeight, pixels, 0, scaledWidth);
    

    请参阅上面的链接以获取逐步替代方案,或使用 imgscalr 之类的库以获得更好的结果。

    如果您真的想使用getScaledInstace(),即使在您阅读了上面的链接之后,您也可以使用ImageProducer/ImageConsumer API,以异步方式获取像素。但是 API 很旧,使用起来有点不方便。

    【讨论】:

    • 问题是我通过 int[] 像素数组绘制图像,我没有使用 g.drawImage() 函数。 getScaledImage() 在调整大小时只会被调用一次,然后我将像素保存到一个数组中,并且在我想要一个新维度之前不必再次调用调整大小。
    • @EvanNudd:再次阅读我的代码。您应该使用 g.drawImage(...) 而不是 Image image = img.getScaledInstance(...) 仅用于创建缩放版本,而不是绘制最终图像。之后您对像素的处理完全取决于您。我已经更新了代码以使其更清晰...... :-)
    • PS:您可以使用pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); 进一步优化您的代码。这是安全的,因为我们使用BufferedImage.TYPE_INT_ARGB 创建了BufferedImage
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    相关资源
    最近更新 更多