package org.andengine.entity.util; import java.nio.IntBuffer; import org.andengine.engine.camera.Camera; import org.andengine.entity.Entity; import org.andengine.opengl.util.GLHelper; import org.andengine.opengl.util.GLState; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.opengl.GLES20; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * @since 15:27:22 - 10.01.2011 */ public class ScreenGrabber extends Entity { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== private int mGrabX; private int mGrabY; private int mGrabWidth; private int mGrabHeight; private boolean mScreenGrabPending; private IScreenGrabberCallback mScreenGrabCallback; // =========================================================== // Constructors // =========================================================== // =========================================================== // Getter & Setter // =========================================================== // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override protected void onManagedDraw(final GLState pGLState, final Camera pCamera) { if (this.mScreenGrabPending) { try { final Bitmap screenGrab = ScreenGrabber.grab(this.mGrabX, this.mGrabY, this.mGrabWidth, this.mGrabHeight); this.mScreenGrabCallback.onScreenGrabbed(screenGrab); } catch (final Exception e) { this.mScreenGrabCallback.onScreenGrabFailed(e); } this.mScreenGrabPending = false; } } @Override protected void onManagedUpdate(final float pSecondsElapsed) { /* Nothing */ } @Override public void reset() { /* Nothing */ } // =========================================================== // Methods // =========================================================== public void grab(final int pGrabWidth, final int pGrabHeight, final IScreenGrabberCallback pScreenGrabCallback) { this.grab(0, 0, pGrabWidth, pGrabHeight, pScreenGrabCallback); } public void grab(final int pGrabX, final int pGrabY, final int pGrabWidth, final int pGrabHeight, final IScreenGrabberCallback pScreenGrabCallback) { this.mGrabX = pGrabX; this.mGrabY = pGrabY; this.mGrabWidth = pGrabWidth; this.mGrabHeight = pGrabHeight; this.mScreenGrabCallback = pScreenGrabCallback; this.mScreenGrabPending = true; } private static Bitmap grab(final int pGrabX, final int pGrabY, final int pGrabWidth, final int pGrabHeight) { final int[] pixelsRGBA_8888 = new int[pGrabWidth * pGrabHeight]; final IntBuffer pixelsRGBA_8888_Buffer = IntBuffer.wrap(pixelsRGBA_8888); // TODO Check availability of OpenGL and GLES20.GL_RGBA combinations that require less conversion operations. GLES20.glReadPixels(pGrabX, pGrabY, pGrabWidth, pGrabHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelsRGBA_8888_Buffer); /* Convert from RGBA_8888 (Which is actually ABGR as the whole buffer seems to be inverted) --> ARGB_8888. */ final int[] pixelsARGB_8888 = GLHelper.convertRGBA_8888toARGB_8888(pixelsRGBA_8888); return Bitmap.createBitmap(pixelsARGB_8888, pGrabWidth, pGrabHeight, Config.ARGB_8888); } // =========================================================== // Inner and Anonymous Classes // =========================================================== public static interface IScreenGrabberCallback { // =========================================================== // Constants // =========================================================== // =========================================================== // Methods // =========================================================== public void onScreenGrabbed(final Bitmap pBitmap); public void onScreenGrabFailed(final Exception pException); } }