Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have rewritten some code to allow to load bitmaps to be loaded as textures and if a pixel has a max green color component it is marked transparent. What is odd is that I cannot use the value from a ByteBuffer that holds transparency without keeping the green intact, I can however replace it with a different color component and the green goes away however then the transparency is altered in an undue way.

public static Texture readTexture(String filename, boolean storeAlphaChannel) throws IOException {
  return readPixels(readImage(filename), storeAlphaChannel);
}

private static Texture readPixels(BufferedImage img, boolean storeAlphaChannel) {
    int[] packedPixels = new int[img.getWidth() * img.getHeight()];

    PixelGrabber pixelgrabber = new PixelGrabber(img, 0, 0, img.getWidth(), img.getHeight(), packedPixels, 0, img.getWidth());
    try {
        pixelgrabber.grabPixels();
    } catch (InterruptedException e) {
        throw new RuntimeException();
    }

    ByteBuffer unpackedPixels = BufferUtil.newByteBuffer(packedPixels.length * 4);

  for (int row = img.getHeight() - 1; row >= 0; row--) {
    for (int col = 0; col < img.getWidth(); col++) {
      int packedPixel = packedPixels[row * img.getWidth() + col];
      if ((byte) ((packedPixel >> 8) & 0xFF) == 127) {
        unpackedPixels.put((byte) -127);
        unpackedPixels.put((byte) -127);
        unpackedPixels.put((byte) -127);
        unpackedPixels.put((byte) -127);
      } 
      else {
        unpackedPixels.put((byte) ((packedPixel >> 0) & 0xFF));  //rgb...a?
        unpackedPixels.put((byte) ((packedPixel >> 8) & 0xFF));
        unpackedPixels.put((byte) ((packedPixel >> 16) & 0xFF));
        //unpackedPixels.put((byte) ((packedPixel >> 24) & 0xFF)); //this makes green come up
        unpackedPixels.put((byte) -((packedPixel >> 0) & 0xFF)); //this makes it look kinda ok, however not pixel perfect(seems different color), other options of changing this to -packedPixel >> 8 have little/no effect. using (byte) 100 makes green show up as well
      }
    }
  }

  unpackedPixels.flip();

  return new Texture(unpackedPixels, img.getWidth(), img.getHeight());
}

public static class Texture {
    private ByteBuffer pixels;
    private int width;
    private int height;

    public Texture(ByteBuffer pixels, int width, int height) {
        this.height = height;
        this.pixels = pixels;
        this.width = width;
    }
    //getters
}

//here is where all the magic happens
int loadTextureGL(String src, boolean wrap) {
    pgl = (PGraphicsOpenGL) g;
    GL gl = (GL) pgl.beginGL();
    game.glu = new GLU();

    gl.glClearColor(0.0, 0.0, 0.0, 0.0);
    gl.glColor3f(0.0, 0.0, 1.0);
    gl.glMatrixMode(GL.GL_MODELVIEW);
    gl.glLoadIdentity();
    if (settings.antialiasing) gl.glEnable(GL.GL_SMOOTH);
    gl.glEnable(GL.GL_BLEND);
    gl.glEnable(GL.GL_TEXTURE_2D);
    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);

    int mtgl = game.mapTextureGL.length+game.sceneryTextureGL.length;

    Texture mapTextureGL = null;
    try {
        println(sketchPath+"/"+src);
        mapTextureGL = readTexture(sketchPath+"/"+src, false);
    } catch (IOException e) {
        e.printStackTrace();
        //return -1;
        throw new RuntimeException(e);
    }
    int[] tmpT = new int[1];
    tmpT[0] = mtgl;

    gl.glGenTextures(1, tmpT, 0);
    gl.glBindTexture(GL.GL_TEXTURE_2D, mtgl);
    gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);

    if (settings.textureMagNearest) {
        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
    } else {
        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
    }
    gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
    gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);

    if (settings.anisotropic && gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic") ) {
        float max[] = new float[1];
        gl.glGetFloatv(GL.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, max, 0);
        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, max[0]);
    }

    try {
        game.glu.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGBA, mapTextureGL.getWidth(), mapTextureGL.getHeight(), GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, mapTextureGL.getPixels());
        makeRGBTexture(gl, game.glu, mapTextureGL, GL.GL_TEXTURE_2D, true);
    } catch(GLException e) {
        System.err.println("Textures failed to bind");
    } catch(BufferUnderflowException e) {
        System.err.println("Textures failed to bind due to underflow");
  }
  pgl.endGL();

  return mtgl;
}
share|improve this question

1 Answer 1

What do you mean, "from a ByteBuffer that holds transparency"? It looks to me like you are writing to a ByteBuffer. Also, what does "this makes green come up" mean?

From my understanding of your code, I can see two problems:

  • The minimum value for a byte is -128, not -127. Lines 21 to 24 should therefore use -128.

  • If a pixel is not transparent, then it I guess it should be opaque. So line 31 should be unpackedPixels.put((byte) 127);

share|improve this answer
    
I meant once the bytes have been added to it, it holds the transparency. When I say it is green, the code should be taking pixels that have a value of 127 (max) green and turning them 100% transparent, if they do not have that they should simply be as transparent as is stored in image (as some graphics are in bitmap and some in png). When I change line 31 to what you say the same error happens, the maxed out green shows completely- this is why I am stumped. –  jett Dec 7 '11 at 15:33
1  
Maybe the endianness of your input data is not the expected one? Try to replace 0, 8, 16, 24 with 24, 16, 8, 0 in your >> operations. By the way, a screenshot (PNG) of your input image and your result would help a lot! –  Sam Hocevar Dec 7 '11 at 15:42
    
imgur.com/e3LOb to show results of endian-testing and green artifact. Please note in first image, I could have done the first three bytes the same as the bottom one, and had gotten the image colors correct- however the trasparancy channel would not have worked and would only be on/off per pixel and that is not what I want since some have gradient transparency. When done 24, 16, 8, 0 the image is very red. It's like something is wrong with the 24 push that makes it behave oddly but I don't see what it could be? I'm guessing it has something to do with how I'm loading the image? –  jett Dec 7 '11 at 21:33
1  
Thanks. Your second screenshot says 16-8-0-24 and gives correct colours but green patches, but your code above says 0-8-16-24 gave correct colours and green patches. Which is which? Did they give similar results? By the way, you shouldn't use -x to get the inverse of a colour, but -1-x, because the range for bytes is -128..127. –  Sam Hocevar Dec 7 '11 at 22:12

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.