I just realized the Bitmap-class behaviour is screwed. If I use the
following method for decoding the bitmap then I get alpha-
premultiplied pixels when calling Bitmap.getPixels:
InputStream is =
context.getResources().openRawResource(texture.resource);
try {
bitmap = BitmapFactory.decodeStream(is, null, sBitmapOptions);
} finally {
is.close();
}
If I use
bitmap = BitmapFactory.decodeResource(context.getResources(),
texture.resource, sBitmapOptions);
then as mentioned Bitmap.getPixels returns non alpha-premultiplied
pixel values. Another difference between these two decode-methods is
that the latter (in my experience) throws out-of-memory exceptions
more frequently than the former, so either the
BitmapFactory.decodeResource-method uses more memory, or it uses more
memory when used in conjunction with my manual texImage2D loading
algorithm.
Of cause nothing is mentioned in the Android javadoc for Bitmap.
Alex
On Aug 12, 10:50 am, arberg <[email protected]> wrote:
> 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
> whatopenglexpects. 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