Add Bitmap image capture capability to GlSurfaceViewRenderer.
PiperOrigin-RevId: 512677893
This commit is contained in:
		
							parent
							
								
									9f59d4d01b
								
							
						
					
					
						commit
						75576700ed
					
				| 
						 | 
					@ -17,6 +17,7 @@ package com.google.mediapipe.components;
 | 
				
			||||||
import static java.lang.Math.max;
 | 
					import static java.lang.Math.max;
 | 
				
			||||||
import static java.lang.Math.min;
 | 
					import static java.lang.Math.min;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.graphics.Bitmap;
 | 
				
			||||||
import android.graphics.SurfaceTexture;
 | 
					import android.graphics.SurfaceTexture;
 | 
				
			||||||
import android.opengl.GLES11Ext;
 | 
					import android.opengl.GLES11Ext;
 | 
				
			||||||
import android.opengl.GLES20;
 | 
					import android.opengl.GLES20;
 | 
				
			||||||
| 
						 | 
					@ -26,9 +27,12 @@ import android.util.Log;
 | 
				
			||||||
import com.google.mediapipe.framework.TextureFrame;
 | 
					import com.google.mediapipe.framework.TextureFrame;
 | 
				
			||||||
import com.google.mediapipe.glutil.CommonShaders;
 | 
					import com.google.mediapipe.glutil.CommonShaders;
 | 
				
			||||||
import com.google.mediapipe.glutil.ShaderUtil;
 | 
					import com.google.mediapipe.glutil.ShaderUtil;
 | 
				
			||||||
 | 
					import java.nio.ByteBuffer;
 | 
				
			||||||
 | 
					import java.nio.ByteOrder;
 | 
				
			||||||
import java.nio.FloatBuffer;
 | 
					import java.nio.FloatBuffer;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.concurrent.atomic.AtomicBoolean;
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicReference;
 | 
					import java.util.concurrent.atomic.AtomicReference;
 | 
				
			||||||
import javax.microedition.khronos.egl.EGLConfig;
 | 
					import javax.microedition.khronos.egl.EGLConfig;
 | 
				
			||||||
import javax.microedition.khronos.opengles.GL10;
 | 
					import javax.microedition.khronos.opengles.GL10;
 | 
				
			||||||
| 
						 | 
					@ -45,6 +49,13 @@ import javax.microedition.khronos.opengles.GL10;
 | 
				
			||||||
 * {@link TextureFrame} (call {@link #setNextFrame(TextureFrame)}).
 | 
					 * {@link TextureFrame} (call {@link #setNextFrame(TextureFrame)}).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class GlSurfaceViewRenderer implements GLSurfaceView.Renderer {
 | 
					public class GlSurfaceViewRenderer implements GLSurfaceView.Renderer {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Listener for Bitmap capture requests.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public interface BitmapCaptureListener {
 | 
				
			||||||
 | 
					    void onBitmapCaptured(Bitmap result);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private static final String TAG = "DemoRenderer";
 | 
					  private static final String TAG = "DemoRenderer";
 | 
				
			||||||
  private static final int ATTRIB_POSITION = 1;
 | 
					  private static final int ATTRIB_POSITION = 1;
 | 
				
			||||||
  private static final int ATTRIB_TEXTURE_COORDINATE = 2;
 | 
					  private static final int ATTRIB_TEXTURE_COORDINATE = 2;
 | 
				
			||||||
| 
						 | 
					@ -64,6 +75,25 @@ public class GlSurfaceViewRenderer implements GLSurfaceView.Renderer {
 | 
				
			||||||
  private float[] textureTransformMatrix = new float[16];
 | 
					  private float[] textureTransformMatrix = new float[16];
 | 
				
			||||||
  private SurfaceTexture surfaceTexture = null;
 | 
					  private SurfaceTexture surfaceTexture = null;
 | 
				
			||||||
  private final AtomicReference<TextureFrame> nextFrame = new AtomicReference<>();
 | 
					  private final AtomicReference<TextureFrame> nextFrame = new AtomicReference<>();
 | 
				
			||||||
 | 
					  private final AtomicBoolean captureNextFrameBitmap = new AtomicBoolean();
 | 
				
			||||||
 | 
					  private BitmapCaptureListener bitmapCaptureListener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Sets the {@link BitmapCaptureListener}.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public void setBitmapCaptureListener(BitmapCaptureListener bitmapCaptureListener) {
 | 
				
			||||||
 | 
					    this.bitmapCaptureListener = bitmapCaptureListener;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Request to capture Bitmap of the next frame.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * The result will be provided to the {@link BitmapCaptureListener} if one is set. Please note
 | 
				
			||||||
 | 
					   * this is an expensive operation and the result may not be available for a while.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public void captureNextFrameBitmap() {
 | 
				
			||||||
 | 
					    captureNextFrameBitmap.set(true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
 | 
					  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
 | 
				
			||||||
| 
						 | 
					@ -149,6 +179,31 @@ public class GlSurfaceViewRenderer implements GLSurfaceView.Renderer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
 | 
					    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
 | 
				
			||||||
    ShaderUtil.checkGlError("glDrawArrays");
 | 
					    ShaderUtil.checkGlError("glDrawArrays");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Capture Bitmap if requested.
 | 
				
			||||||
 | 
					    BitmapCaptureListener bitmapCaptureListener = this.bitmapCaptureListener;
 | 
				
			||||||
 | 
					    if (captureNextFrameBitmap.getAndSet(false) && bitmapCaptureListener != null) {
 | 
				
			||||||
 | 
					      int bitmapSize = surfaceWidth * surfaceHeight;
 | 
				
			||||||
 | 
					      ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bitmapSize * 4);
 | 
				
			||||||
 | 
					      byteBuffer.order(ByteOrder.nativeOrder());
 | 
				
			||||||
 | 
					      GLES20.glReadPixels(
 | 
				
			||||||
 | 
					          0, 0, surfaceWidth, surfaceHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuffer);
 | 
				
			||||||
 | 
					      int[] pixelBuffer = new int[bitmapSize];
 | 
				
			||||||
 | 
					      byteBuffer.asIntBuffer().get(pixelBuffer);
 | 
				
			||||||
 | 
					      for (int i = 0; i < bitmapSize; i++) {
 | 
				
			||||||
 | 
					        // Swap R and B channels.
 | 
				
			||||||
 | 
					        pixelBuffer[i] =
 | 
				
			||||||
 | 
					            (pixelBuffer[i] & 0xff00ff00)
 | 
				
			||||||
 | 
					                | ((pixelBuffer[i] & 0x000000ff) << 16)
 | 
				
			||||||
 | 
					                | ((pixelBuffer[i] & 0x00ff0000) >> 16);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      Bitmap bitmap = Bitmap.createBitmap(surfaceWidth, surfaceHeight, Bitmap.Config.ARGB_8888);
 | 
				
			||||||
 | 
					      bitmap.setPixels(
 | 
				
			||||||
 | 
					          pixelBuffer, /* offset= */bitmapSize - surfaceWidth, /* stride= */-surfaceWidth,
 | 
				
			||||||
 | 
					          /* x= */0, /* y= */0, surfaceWidth, surfaceHeight);
 | 
				
			||||||
 | 
					      bitmapCaptureListener.onBitmapCaptured(bitmap);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GLES20.glBindTexture(textureTarget, 0);
 | 
					    GLES20.glBindTexture(textureTarget, 0);
 | 
				
			||||||
    ShaderUtil.checkGlError("unbind surfaceTexture");
 | 
					    ShaderUtil.checkGlError("unbind surfaceTexture");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user