【问题标题】:Using IntBuffer for BufferedImage将 IntBuffer 用于 BufferedImage
【发布时间】:2013-11-18 22:51:49
【问题描述】:

正如标题 aleady 所说,它想要创建一个由特定(已经存在的)IntBuffer 支持的 BufferedImage。

到目前为止,我有以下代码:

final IntBuffer buf = ...;
DataBuffer dbuf = new DataBuffer(DataBuffer.TYPE_INT,size) {
    public void setElem(int bank, int i, int val) {
        buf.put(i,val);
    }
    public int getElem(int bank, int i) {
        return buf.get(i);
    }
};
ColorModel cm = ColorModel.getRGBdefault();
SampleModel sm = cm.createCompatibleSampleModel(dim.width,dim.height);
WritableRaster raster = WritableRaster.createWritableRaster(sm,dbuf,null);
BufferedImage img = new BufferedImage(cm,raster,false,new Hashtable<>());

但此代码显示以下错误:

Exception in thread "main" java.awt.image.RasterFormatException: IntegerComponentRasters must haveinteger DataBuffers
at sun.awt.image.IntegerComponentRaster.<init>(Unknown Source)
at sun.awt.image.IntegerInterleavedRaster.<init>(Unknown Source)
at sun.awt.image.IntegerInterleavedRaster.<init>(Unknown Source)
at java.awt.image.Raster.createWritableRaster(Unknown Source)
at test.Test.main(Test.java:100)

(该行是创建 WritableRaster 的行。) 对我来说,不必复制数据非常重要,因为我将主要使用 BufferedImage 作为一个舒适的接口来写入底层 IntBuffer(有一些例外)。

【问题讨论】:

  • 你是从其他论坛复制的吗?不要在每一行之后放置&lt;br&gt; 标签。 SO 有自己的格式。
  • 我已尝试修复您帖子的格式,但请在发布前阅读任何网站的编辑建议。感谢您今后在这方面的合作。
  • 我尝试正确格式化,但我的英语不是最好的。所以关于这个主题的帮助文件让我很困惑。但是,感谢您对其进行格式化。当然,我没有从任何地方复制它,而是通过反复试验自己编程。 (在违反版权法可能要花费数千欧元的时候,复制和粘贴可能不是一个好主意。)

标签: java image bufferedimage


【解决方案1】:

我有一个非常相似的问题,试图创建一个由 nio ByteBuffer 支持的 DataBuffer。您尝试做的事情是可能的,但不使用Raster.createWritableRaster 方法(我认为这是一个错误,但多年来一直如此,所以不要指望它会很快得到修复)。您需要直接创建可写栅格的实例。

要么:

WritableRaster = new sun.awt.image.SunWritableRaster(...);

或者,创建您自己的 WritableRaster 子类(这很简单,您实际上不需要重写任何方法,可能需要 toString 来帮助调试)。

class GenericWritableRaster extends WritableRaster {
    public GenericWritableRaster(SampleModel model, DataBuffer buffer, Point origin) {
        super(model, buffer, origin);
    }
}

WritableRaster = new GenericWritableRaster(...);

要获得一些灵感,您可以查看我的GenericWritableRaster 实现,以及
MappedImageFactory 类了解如何使用它。

生成的图像将始终为BufferedImage.TYPE_CUSTOM 类型(因此从 Java 中可能会很慢),但如果您有一个库已经将图像保存在显卡的 RAM 中,这对您来说可能没有问题。


更新,这是一个基于您的代码的 SSCCE PoC:

public class BufferTest {
    public static void main(String[] args) {
        Dimension dim = new Dimension(100, 100);
        int size = dim.width * dim.height;

        final IntBuffer buf = IntBuffer.wrap(new int[size]);

        DataBuffer dbuf = new DataBuffer(DataBuffer.TYPE_INT, size) {
            public void setElem(int bank, int i, int val) {
                buf.put(i, val);
            }

            public int getElem(int bank, int i) {
                return buf.get(i);
            }
        };
        ColorModel cm = ColorModel.getRGBdefault();
        SampleModel sm = cm.createCompatibleSampleModel(dim.width, dim.height);
        WritableRaster raster = new WritableRaster(sm, dbuf, new Point()) {};
        BufferedImage img = new BufferedImage(cm, raster, false, null);

        System.err.println("img: " + img);
    }
}

打印:

img: BufferedImage@234441b6: type = 0 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 com.twelvemonkeys.image.BufferTest$2@563625d0

【讨论】:

    【解决方案2】:

    我查看了IntegerComponentRaster 的字节码,它引发了您的异常,它明确检查您传入的DataBuffer 实例是否是DataBufferInt 的子类。 不幸的是,你不能轻易地扩展这个类,因为它被声明为final。所以恐怕你不能做你需要的。

    作为替代方案,也许您可​​以先创建DataBuffer,然后将其内容包装在IntBuffer 中?像这样的:

    DataBufferInt dbuf = new DataBufferInt(size);
    IntBuffer buf = IntBuffer.wrap(dbuf.getData());
    // Fill the IntBuffer etc...
    

    【讨论】:

    • 感谢您分析 IntegerComponentRaster。这对我来说是个坏消息,因为重要的是数据分配在 IntBuffer 中,而不是在 DataBuffer 中。我无法直接访问原始数据 (int[]),因为它大部分时间都直接存储在显卡中并由第三方库处理。只有使用 IntBuffer 提供的方法才能写入和读取此数据。
    猜你喜欢
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 2017-12-03
    相关资源
    最近更新 更多