Java2D & Native Buffers
Frederick:
Hey!
This is a java2d - opengl related question.
Basically I want to draw into a BufferedImage and pass that image as OpenGL texture.
I know there is a method to create a ByteBuffer from BufferedImage - it looks like this:
1
2
byte[] imageArray = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
ByteBuffer imageBuffer = ByteBuffer.wrap(imageArray);
However this won´t work for me, because I need the buffer to be direct, the buffer retrieved
by this method is not direct. Unfortunately my JNI methods (yes thats right - I rolled my own ;D )
won´t accept non direct buffers. A hacky and a performancewise not so optimal solution may
be to copy the non-direct buffer into a direct buffer, but I really wouldn´t like my little program
to spend time on copying ;)
So is there a way to wrap a BufferedImage around a direct buffer ? Technically that should be
no problem...
Riven:
Unfortunately, you'll have to copy the byte[] into a direct buffer yourself.
The problem is, that as long as we cannot pin down objects (the GC must not move these objects in the heap) we can't make a direct buffer point to these memory-locations. Further, I highly doubt anybody at Sun would be willing to change the public API to give everybody and their dog access to BufferedImage internals, as those seem to get rehauled every few years..
Frederick:
Okay I am a bit frustrated by now !
I found a way to solve that problem.
Sun engineers have nicely abstracted all properties of a graphics surface.
The key class is WritableRaster which uses a DataBuffer. A DataBuffer is an encapsulation of the actual data representation. For example the most used implementation of DataBuffer is the DataBufferByte which is implemented by a byte array. So the way to go is implement an own version of Data Buffer:
Quote
public class DataBufferDirectByte extends DataBuffer {
protected ByteBuffer directByteBuffer;
public DataBufferDirectByte(ByteBuffer directByteBuffer) {
super(TYPE_BYTE, directByteBuffer.capacity());
this.directByteBuffer = directByteBuffer;
}
public int getElem(int bank, int i) {
return directByteBuffer.get(i);
}
public void setElem(int bank, int i, int val) {
directByteBuffer.put(i, (byte)val);
}
public ByteBuffer getDirectByteBuffer() {
return directByteBuffer;
}
}
Very Easy uh ? ;)
Afterwards one has to wade through lots of other classes, there need to be surfaceformats and colormodels defined before it is finally possible to build an ImageBuffer.
This looks like this:
Quote
int[] offsetarray = {0,1,2,3};
PixelInterleavedSampleModel smodel =
new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, 256,256,4,256*4,offsetarray);
WritableRaster r = (WritableRaster) Raster.createRaster(smodel,
new DataBufferDirectByte(BufferUtils.allocateDirectByteBuffer(256*4)), new Point(0,0));
ColorModel m = ImageUtil.createColorModel(r.getSampleModel());
BufferedImage i = new BufferedImage(m,r,false, null
);
The BufferUtils class was written by me.
But then happens the big #!$5$!*
Quote
ByteComponentRasters must have byte DataBuffers
java.awt.image.RasterFormatException: ByteComponentRasters must have byte DataBuffers
at sun.awt.image.ByteComponentRaster.<init>(ByteComponentRaster.java:142)
A class somewhere inside the jdk jungle complains that our newly introduced DataBuffer is not of byte type. What the *!& ? We have defined it to be of byte type by calling the constructor of the superclass with the apropriate parameter;
1
super(TYPE_BYTE, directByteBuffer.capacity());
The type might be queried then with the DataBuffer.getDataType method.
Then I have a look at the implementation of this "ByteComponentRasters" class and what do i find ???
1
2
3
4
5
6
if (!(dataBuffer instanceof DataBufferByte)) {
throw new RasterFormatException(
"ByteComponentRasters must have "
+ "byte DataBuffers");
}
That makes me wanna cry ! They actually confused their design ! They are checking the actual class types, instead they should
have been using:
switch(dataBuffer.getDataType);
Oh nooo! I actually think that this is a bug and was not meant this way. No point in abstracting everything, so the system may nicely be extended, and then to allow only one type.
>:( >:( >:( >:(
No more motivation to continue...
What do you think about this ?
tom:
You could access the BufferedImage array directly from your JNI method?
Frederick:
Hey Tom I am trying to do that ;D
But I believe the only way to access *ANYTHING* via JNI is to put
it into direct buffers. I would never pass java objects down to c++, for
perfomance reasons. I believe it was a wrong decision from sun
(at least for my purposes) design JNI like it is now. It would have been
better if C++ could directly access java class fields and methods, even
if that would mean recompiling the dll if a new java version comes
around.
If I remember correctly the issue with accessing java arrays from c++
is that the arrays gets copied or something. I will have a look at that later.
Have to go to uni,
Thanks
Frederick
Navigation
[0] Message Index
[#] Next page