Regarding the big-endian comment in the code, I meant little-endian.
If we use IntBuffer to write ABGR ints to ByteBuffer on a little-
endian-phone we get byte order we RGBA. However the same code running
on a big-endian phone should produce ABGR byte order, which is not
what opengl expects. So don't use intbuffer.

The following should also work, and allocates less memory, but I don't
quite trust it since I don't have a big-endian phone, and since I
cannot test it on a big-endian emulator:

        private static final boolean IS_LITTLE_ENDIAN =
(ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
        private void myTexImage2D(GL10 gl, Bitmap bitmap) {
                // Don't loading using GLUtils, load using gl-method directly
                // GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
                int[] pixels = extractPixels(bitmap);
                for (int i = pixels.length - 1; i >= 0; i--) {
                        int p = pixels[i];
                        int r = ((p >> 16) & 0xFF);
                        int g = ((p >> 8) & 0xFF); // green
                        int b = ((p) & 0xFF); // blue
                        int a = (p >> 24); // alpha
                        if (IS_LITTLE_ENDIAN) {
                                pixels[i] = a << 24 | b << 16 | g << 8 | r;
                        } else {
                                pixels[i] = r << 24 | g << 16 | b << 8 | a;
                        }
                }
                IntBuffer pixelBuffer = IntBuffer.wrap(pixels);

                gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA,
bitmap.getWidth(), bitmap.getHeight(), 0, GL10.GL_RGBA,
GL10.GL_UNSIGNED_BYTE, pixelBuffer);
        }



Alex

On Aug 12, 10:17 am, arberg <[email protected]> wrote:
> Apparently the cause of thepremultipliedalphalies in GLUtils, or
> perhaps the way GLUtils works with the Bitmap class. We can get the
> correct non-premultipliedalphabehaviour by replacing
> GLUtils.texImage2D with theopenglmethod gl.glTexImage2D which takes
> a pixel component array as a parameter. Thus we can avoid 
> thepremultipliedalphabehaviour, which means we can use the blend
> function gl.glBlendFunc(GL10.GL_SRC_ALPHA,
> GL10.GL_ONE_MINUS_SRC_ALPHA);
>
> Note for uninitiated confusedopenglandroid developers: I posted a
> question onopengl.org discussion forum, where I described the
> symptoms of the 
> problem:http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&N...
>
> Here's how I loaded the image in Android:
>
>     private int loadTexture(GL10 gl, int resourceId) {
>         int[] textureNameWorkspace = new int[1];
>                 gl.glGenTextures(1, textureNameWorkspace, 0);
>                 int textureName = textureNameWorkspace[0];
>                 gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
>                 gl.glTexParameterf(GL10.GL_TEXTURE_2D, 
> GL10.GL_TEXTURE_MIN_FILTER,
> GL10.GL_LINEAR);
>                 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_REPEAT);
>                 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
> GL10.GL_REPEAT);
>
>                 gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
> GL10.GL_MODULATE);
>
>         Bitmap bitmap = BitmapFactory.decodeResource(resources,
> resourceId);
>         myTexImage2D(gl, bitmap);
>         // Set the crop parameter because I use drawtexture extension
>                 ((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
> GL11Ext.GL_TEXTURE_CROP_RECT_OES,
>                                 new int[] { 0, bitmap.getHeight(), 
> bitmap.getWidth(), -
> bitmap.getHeight() }, 0);
>                 return textureName;
>         }
>
>         private void myTexImage2D(GL10 gl, Bitmap bitmap) {
>                 // Don't loading using GLUtils, load using gl-method directly
>         // GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
>         int[] pixels = extractPixels(bitmap);
>         byte[] pixelComponents = new byte[pixels.length*4];
>         int byteIndex = 0;
>         for (int i = 0; i < pixels.length; i++) {
>                 int p = pixels[i];
>                         // Convert to byte representation RGBA required by 
> gl.glTexImage2D.
>                         // We don't use intbuffer, because then we
>                         // would be relying on the intbuffer wrapping to 
> write the ints in
>                         // big-endian format, which means it would work for 
> the wrong
>                         // reasons, and it might brake on some hardware.
>                 pixelComponents[byteIndex++] = (byte) ((p >> 16) & 0xFF); // 
> red
>                 pixelComponents[byteIndex++] = (byte) ((p >> 8) & 0xFF); //
> green
>                 pixelComponents[byteIndex++] = (byte) ((p) & 0xFF); // blue
>                 pixelComponents[byteIndex++] = (byte) (p >> 24);  //alpha
>         }
>         ByteBuffer pixelBuffer = ByteBuffer.wrap(pixelComponents);
>
>         gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA,
> bitmap.getWidth(), bitmap.getHeight(), 0, GL10.GL_RGBA,
> GL10.GL_UNSIGNED_BYTE, pixelBuffer);
>         }
>
>         public static int[] extractPixels(Bitmap src) {
>                 int x = 0;
>                 int y = 0;
>                 int w = src.getWidth();
>                 int h = src.getHeight();
>                 int[] colors = new int[w * h];
>                 src.getPixels(colors, 0, w, x, y, w, h);
>                 return colors;
>         }
>
> Since the above implementation does not use native code to convert the
> bitmap and since it also allocates the bitmap array twice besides
> loading the bitmap (thus taking three times the memory space) its not
> quite optimal. It would be quite reasonable that Android supplied a
> native method for doing this. Certainly the documenation for GLUtils
> should state that it loads apremultipliedalphatexture. Does anyone
> know if there is a bugreport/feature request on this on Android? I
> cant seem to find any mentioning of it in the issue 
> list:http://code.google.com/p/android/issues/list
>
> Alex.

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to