Transparency with textures

Okay... making progress with texturing, but I'm now having a problem with setting alpha values. The code below sets a BufferedImage from a url and then sets a 4 byte RGBA texture from it by copying the RGB bytes and adding an alpha byte as the maximum value of the RGB bytes.

Problems:

1. The bytes from the input image don't translate directly as RGB; to get the right colours I have to reverse them (see code).

2. The alpha values are strange: the texture seems too transparent; when I set alpha explicitly to zero it doesn't appear at all (Java specifies that zero = no transparency); and when I set alpha to 255 it is still quite transparent.

Any image experts that might have some idea what I'm doing wrong here?

publicvoid LoadTexture3D(URL url){

BufferedImage urlImage;

try{

urlImage = ImageIO.read(url);

}

catch (IOException e){

e.printStackTrace();

return;

}

width = urlImage.getWidth();

height = urlImage.getHeight();

depth = 4;// urlImage.getWidth();

byte[] origData = ((DataBufferByte)urlImage.getData().getDataBuffer()).getData();

ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);

int[] nBits ={8, 8, 8, 8};

ComponentColorModel colorModel =new ComponentColorModel(cs, nBits, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);

WritableRaster raster = colorModel.createCompatibleWritableRaster(width, height);

BufferedImage bImage =new BufferedImage(colorModel, raster, false,null);

byte[] byteData = ((DataBufferByte)raster.getDataBuffer()).getData();

ImageComponent3D pArray =new ImageComponent3D(ImageComponent.FORMAT_RGBA, width, height, depth);

for (int j = 0; j < height; j++)

for (int i = 0; i < width; i++){

int indexb = ((j * width) + i) * 4;

int indexo = ((j * width) + i) * 3;

byteData[indexb + 2] = origData[indexo];

byteData[indexb + 1] = origData[indexo + 1];

byteData[indexb + 0] = origData[indexo + 2];

//calculate alpha

int alpha = Math.max(Math.max(byteToInt(origData[indexo]), byteToInt(origData[indexo + 1])), byteToInt(origData[indexo + 2]));

//alpha = 255;

byte test = (byte)alpha;

byteData[indexb + 3] = test;

}

for (int k = 0; k < depth; k++)

pArray.set(k, bImage);

texture3D =new Texture3D(Texture.BASE_LEVEL,

Texture.RGBA,

width,

height,

depth);

texture3D.setImage(0, pArray);

texture3D.setEnable(true);

texture3D.setMinFilter(Texture.BASE_LEVEL_LINEAR);

texture3D.setMagFilter(Texture.BASE_LEVEL_LINEAR);

texture3D.setBoundaryModeS(Texture.CLAMP);

texture3D.setBoundaryModeT(Texture.CLAMP);

texture3D.setBoundaryModeR(Texture.CLAMP);

}

privateint byteToInt(byte b){

int val = (int)b;

if (val < 0) val += 256;

return val;

}

To set the transparency node:

TransparencyAttributes t =new TransparencyAttributes();

t.setTransparencyMode(TransparencyAttributes.BLENDED);

t.setSrcBlendFunction(TransparencyAttributes.BLEND_SRC_ALPHA);

thisAppNode.setTransparencyAttributes(t);

[4740 byte] By [typicallya] at [2007-11-26 17:24:37]
# 1

Hi again tipically :)

I'll try to answer to your questions.

1) RGBA inversed. I don't know exactly the format you're using; but I know that Java load integer values with Most Significant Byte First, instead other processors, like Intel, loads byte with Less Significant Byte First. ( ABCD vs DCBA ). This was a problem also for me when I tried to load a file saved by an Intel machine.

2) There is a little confusion IMHO about alpha channel. In an RGBA format, the value of alpha is between 0 and 1 (0 and 255) and is the multiplier factor for the transparency. In the case of Java Appearance, a value of 1.0 is a complete transparency, instead in the alpha channel RGBA 1.0 is complete opacity! I suggest to use alpha channel RGBA = 1.0 and use the appearance transparency attributes. I guess that the RGBA format is not even necessary.

I hope these arguments are valid!

Check this also:

http://en.wikipedia.org/wiki/Alpha_compositing

/cheers!

sigua at 2007-7-8 23:52:38 > top of Java-index,Security,Cryptography...
# 2

Hi sigu, thanks for answering.

Okay, so here's my progress. Windows apparently likes to save things in BGR format, inverting the standard (go figure). I can test for the format with the function BufferedImage.getType(). So, with this in mind I can set the RGB bytes no problem. The alpha channel I add also seems fine. I ascertained this by running the same filter on an image and rendering it in Java2D. The transparency works exactly like I want it to, making less intense pixels more transparent.

So... the problem is definitely with Java3D transparencies. I have, as you suggested, given the image a general transparency and this works fine as a Texture2D. However, I need to be able to assign alpha to individual pixels, since I want to render a 3D volume consisting of a stack of images (e.g. MRI images of the brain). For this I need the RGBA format, and some way of making the blending functions work.

I'm guessing there's something quite simple at the bottom of this (there usually is), so I'll be digging further into the TransparencyAttributes and RenderingAttributes classes, but any further insight is welcome =)

typicallya at 2007-7-8 23:52:38 > top of Java-index,Security,Cryptography...