3

I create an image in Java 6, using a Mac computer with the code below. I then try to display that image in an Android device using OpenGL ES. The image does not not get displayed and only a white image gets displayed. However, if there are no translucent pixels then the image gets displayed fine.

I have no problems displaying translucent images created in Photoshop. It is only with translucent images created in Java that I have a problem. I've also tried different methods of creating a translucent image with Java and I always get the same result, a white image displayed in OpenGL. At this point I believe this is a bug with Java, (In a Mac computer). has anybody ever run into something like this? Any idea why this might be happening?

//Code for creating an image

int cmap[] = { 
0x00000000, /*transparent*/ 
0xFF000000, /*black*/ 
0xFFFF0000, /*red*/ 
0xFFFFFF00, /*yellow*/ 
0xFF00FF00, /*green*/ 
//...... 
}; 
IndexColorModel colorModel = new IndexColorModel(8, 
cmap.length, cmap, 0, true, -1, DataBuffer.TYPE_BYTE); 
BufferedImage image = new BufferedImage(256, 256, 
BufferedImage.TYPE_BYTE_INDEXED, colorModel); 
Graphics2D g = image.createGraphics(); 
g.setBackground(new Color(0,0,0,0)); /*transparent*/ 
g.clearRect(0 , 0, image.getWidth(), image.getHeight()); 
g.setColor(Color.red); 
g.draw(new Rectangle(10, 10, 40, 40));


ImageIO.write(image, "PNG", new File("rectangle.png")); 

Below is the code for loading the texture. Please note that this is specific to the Android environment.

public static void loadAndBindTexture(GL10 gl) throws Exception
{ 
    int numberTextures=1;
    int[] textures = new int[numberTextures];
    gl.glGenTextures(numberTextures, textures, 0);
    int textureID=textures[0];

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);//polyBreaker3DObject_.mTextureID);

    checkGLError(gl, 998);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_LINEAR);
    checkGLError(gl, 997);
    //NOTE: FOR GL_TEXTURE_MAG_FILTER only GL_NEAREST or GL_LINEAR are valid.
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    checkGLError(gl, 996);

    /*Commented on Sept. 30, 2010 6:21AM
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
    */
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_CLAMP_TO_EDGE);
    checkGLError(gl, 1000);

    gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,GL10.GL_DECAL);
    checkGLError(gl, 1001);
    gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
    checkGLError(gl, 1002);


 if(mContext==null)//mContext is the Context of the current Android application (it is set before this method is called
    throw new Exception("Context has not been set.");
 InputStream is = mContext.getResources().openRawResource(R.drawable.metal128x128);//blueski);//robot);
Bitmap bitmap;
try {

    bitmap = BitmapFactory.decodeStream(is);

} finally {
    try {
        is.close();
    } catch(IOException e) {
        Log.printCaughtExceptionMsg(e);
    }
}

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();

   checkGLError(gl, 1003);

}
Felipe
  • 29
  • 3
  • Can you show the code you use to load the image and create the texture from it? Especially the glTexImage2D call – haffax Apr 12 '12 at 14:18

2 Answers2

1

Can you post the actual call to glDrawElements() or glDrawArrays()? It's hard to tell what you are doing wrong without looking looking at the actual OpenGL draw call. But it's possible that you are not enabling blending before you draw the texture.

Something like this should do the trick:

gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_BLEND);

Take a look at this question if you want a little more information.

EDIT:

My mistake, I misread your question. You should take a look at the BufferedImage format you are using. TYPE_BYTE_INDEXED doesn't seem to support alpha values based on the documentation. Have you tried using TYPE_INT_ARGB instead?

Community
  • 1
  • 1
theisenp
  • 8,639
  • 5
  • 39
  • 47
  • Thanks for the answer. I am enabling blending. As I mentioned, the rendering of translucent textures work fine for translucent images created using Photoshop. – Felipe Apr 13 '12 at 17:59
  • Sorry about that, I misread the question. I've updated my answer. – theisenp Apr 13 '12 at 18:08
0

I still have not really been able to figure out why transparent images created with Java do not work in Android OpenGL ES. However, I did find a hack that allows the images to work.

When you create your new transparent image in java, the first thing that you should do is to draw a semi-transparent image on it using the method call

        g.drawImage(Image img, x, y,  null);

//g is a Graphics object obtained from the new image being created

//img argument is a semi transparent, not 100% transparent (or else it will not work) image created in Photoshop. I use a 4x4 size so that it won't be noticeable.

After this call you can go ahead and continue executing your original code. The new image will now work in Android OpenGL ES.

My guess is that by drawing a semi transparent image it changes the format of the PNG file generated, and this format change makes it work in Android OpenGL ES.

Felipe
  • 29
  • 3