Author Topic: new Texture(Bitmap) and Bitmap.recycle()  (Read 2972 times)

Offline Luca

  • byte
  • *
  • Posts: 2
    • View Profile
new Texture(Bitmap) and Bitmap.recycle()
« on: October 07, 2011, 04:22:21 pm »
Hello, I'm new in jpct.

I try to create an overlay on a 3d scene with FrameBuffer.blit(...). I want a dynamic overlay, so i use a Bitmap to create a Texture to pass at FrameBuffer.blit(...).

But i have found this error:
10-07 16:10:18.512: ERROR/AndroidRuntime(32002): java.lang.RuntimeException: [ 1317996618471 ] - ERROR: java.lang.IllegalStateException: Can't call getPixels() on a recycled bitmap

I deduce that this error is caused by a call of Bitmap.recycle() in Texture constructor.

I try to create everytime a new Bitmap in each iteration but in android cause out of memory error.

How can I do a dynamic overlay?

ps. sorry for may bad english.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11970
    • View Profile
    • http://www.jpct.net
Re: new Texture(Bitmap) and Bitmap.recycle()
« Reply #1 on: October 07, 2011, 09:30:10 pm »
recycle() should only the called on Bitmaps that the constructor creates internally, not on those that you've created yourself. Here's a fixed version: http://jpct.de/download/beta/jpct-ae.jar

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11970
    • View Profile
    • http://www.jpct.net
Re: new Texture(Bitmap) and Bitmap.recycle()
« Reply #2 on: October 07, 2011, 09:33:37 pm »
However, if you want to change the texture at runtime, ITextureEffect is the better solution.

Offline Luca

  • byte
  • *
  • Posts: 2
    • View Profile
Re: new Texture(Bitmap) and Bitmap.recycle()
« Reply #3 on: October 08, 2011, 01:05:25 pm »
Thank you so much...
I resolve the problem using ITextureEffect, this is the code:
Code: [Select]
private Bitmap overlayBitmap = null;
private Canvas overlayCanvas = null;
private Texture overlay = null;
private void drawOverlay(int width, int height) {
if(overlayBitmap == null || nextPow2(width) != overlayBitmap.getWidth() || nextPow2(height) != overlayBitmap.getHeight()){
overlayBitmap = Bitmap.createBitmap(nextPow2(width), nextPow2(height), Bitmap.Config.ARGB_8888);
overlayCanvas = new Canvas(overlayBitmap);
overlay = new Texture(Bitmap.createBitmap(overlayBitmap));
overlay.setEffect(new ITextureEffect() {
@Override
public void init(Texture arg0) {}

@Override
public boolean containsAlpha() {
return true;
}

@Override
public void apply(int[] dest, int[] src) {
overlayBitmap.getPixels(dest, 0, overlay.getWidth(), 0, 0, overlay.getWidth(), overlay.getHeight());
}
});
}

overlayCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

//Paint what you want
Paint p = new Paint();
p.setColor(Color.CYAN);
overlayCanvas.drawText("" + (SystemClock.uptimeMillis() / 1000), 50, 50, p);
//End Paint

overlay.applyEffect();
}

public int nextPow2(int num) {
return (int)Math.pow(2, num == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(num - 1));
}

And in onDrawFrame:
[...]
Code: [Select]
drawOverlay(fb.getWidth(), fb.getHeight());
fb.blit(overlay, 0, 0, 0, 0, fb.getWidth(), fb.getHeight(), true);
[...]