cameraX在使用previewView时,如何为preview添加滤镜
时间: 2024-03-17 09:42:46 浏览: 26
要为 CameraX 的预览界面添加滤镜,需要使用 SurfaceTextureListener 接口来监听 CameraX 的预览界面 SurfaceTexture 的创建和销毁事件。在 SurfaceTexture 创建之后,可以将其转换为 Surface 对象,再将 Surface 对象传递给 MediaCodec 进行编码,实现预览界面滤镜的效果。
以下是一个使用 CameraX 和 OpenGL ES 滤镜库 Grafika 实现预览界面滤镜的示例代码:
```java
public class CameraXActivity extends AppCompatActivity implements SurfaceTextureListener {
private PreviewView mPreviewView;
private CameraX.LensFacing mLensFacing = CameraX.LensFacing.BACK;
private Executor mExecutor = Executors.newSingleThreadExecutor();
private int mTextureId = -1;
private EglCore mEglCore;
private WindowSurface mWindowSurface;
private Texture2dProgram mTextureProgram;
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_x);
mPreviewView = findViewById(R.id.preview_view);
mPreviewView.setSurfaceTextureListener(this);
// 初始化 OpenGL ES 相关对象
mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
mTextureProgram = new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT);
mTextureId = mTextureProgram.createTextureObject();
// 启动 CameraX
CameraX.bindToLifecycle(this, new Preview.Builder().build());
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
// 将 SurfaceTexture 转换为 Surface 对象
mSurfaceTexture = surfaceTexture;
mSurface = new Surface(surfaceTexture);
// 创建 OpenGL ES 窗口
mWindowSurface = new WindowSurface(mEglCore, mSurface, false);
mWindowSurface.makeCurrent();
// 设置预览界面滤镜
mTextureProgram.setTextureSize(width, height);
mTextureProgram.drawFrame(mTextureId, true);
// 开始 CameraX 预览
startPreview();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
// 重新设置预览界面滤镜的尺寸
mTextureProgram.setTextureSize(width, height);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
// 销毁 OpenGL ES 相关对象
mWindowSurface.release();
mTextureProgram.release();
GLES20.glDeleteTextures(1, new int[] { mTextureId }, 0);
mEglCore.release();
// 停止 CameraX 预览
stopPreview();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
// 实时更新预览界面滤镜
mTextureProgram.drawFrame(mTextureId, true);
mWindowSurface.swapBuffers();
}
private void startPreview() {
ListenableFuture<ProcessCameraProvider> providerFuture = ProcessCameraProvider.getInstance(this);
providerFuture.addListener(() -> {
try {
ProcessCameraProvider provider = providerFuture.get();
Preview preview = new Preview.Builder().build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(mLensFacing)
.build();
provider.unbindAll();
provider.bindToLifecycle(this, cameraSelector, preview);
preview.setSurfaceProvider(() -> mSurface);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
Toast.makeText(CameraXActivity.this, "启动相机失败", Toast.LENGTH_SHORT).show();
}
}, mExecutor);
}
private void stopPreview() {
ListenableFuture<ProcessCameraProvider> providerFuture = ProcessCameraProvider.getInstance(this);
providerFuture.addListener(() -> {
try {
ProcessCameraProvider provider = providerFuture.get();
provider.unbindAll();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}, mExecutor);
}
}
```
其中,Texture2dProgram 是 Grafika 中的一个 OpenGL ES 滤镜库,EglCore 封装了 EGL 的一些常用操作,WindowSurface 封装了 EGL 的窗口相关操作。在 SurfaceTextureListener 的回调方法中,使用 Texture2dProgram 将预览帧渲染到 OpenGL ES 窗口中,实现预览界面滤镜的效果。