使用IntBuffer for BufferedImage

时间:2013-11-17 00:13:39

标签: java image bufferedimage

正如标题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的舒适接口(除了少数例外)。

2 个答案:

答案 0 :(得分:1)

我查看了IntegerComponentRaster的字节码,它抛出了你的异常,它显式检查你传入的DataBuffer实例是否是DataBufferInt的子类。 不幸的是,您无法轻松扩展此类,因为它已声明为final。所以我担心你不能做你需要的。

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

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

答案 1 :(得分:1)

我遇到了一个非常类似的问题,尝试创建由nio DataBuffer支持的ByteBuffer。您尝试做的是可能的,但不使用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中,则可能没有问题。< / p>


更新,这是基于您的代码的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