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.min;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.opengl.GLES11Ext;
|
||||
import android.opengl.GLES20;
|
||||
|
@ -26,9 +27,12 @@ import android.util.Log;
|
|||
import com.google.mediapipe.framework.TextureFrame;
|
||||
import com.google.mediapipe.glutil.CommonShaders;
|
||||
import com.google.mediapipe.glutil.ShaderUtil;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
@ -45,6 +49,13 @@ import javax.microedition.khronos.opengles.GL10;
|
|||
* {@link TextureFrame} (call {@link #setNextFrame(TextureFrame)}).
|
||||
*/
|
||||
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 int ATTRIB_POSITION = 1;
|
||||
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 SurfaceTexture surfaceTexture = null;
|
||||
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
|
||||
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);
|
||||
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);
|
||||
ShaderUtil.checkGlError("unbind surfaceTexture");
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user