为什么相机库CameraView预览和拍照的效果不一致 ? |
您所在的位置:网站首页 › 谷歌相机拍的照片预览不了 › 为什么相机库CameraView预览和拍照的效果不一致 ? |
1. 前言
在项目中,我们经常使用到CameraView,遇到好几次预览和拍照实际的效果不一致的情况。 这是为什么呢,为什么使用滤镜的时候,CameraView拍照和预览的效果会不一致 ? 终于在CameraView的源码里找到了答案。 2. takePictureSnapshot带滤镜拍照的入口是CameraView.takePictureSnapshot() cameraView.takePictureSnapshot()cameraView.takePictureSnapshot()会调用到mCameraEngine.takePictureSnapshot(), 这个PictureResult.Stub是一个参数封装类,这里重新创建了一个PictureResult.Stub并传入takePictureSnapshot()方法中。 mCameraEngine是CameraEngine抽象类,实现类有Camera1Engine和Camera2Engine。 public void takePictureSnapshot() { PictureResult.Stub stub = new PictureResult.Stub(); mCameraEngine.takePictureSnapshot(stub); }我们这里以Camera2为例,可以看到这里对stub参数封装类赋值了一些参数(摄像头ID、图片格式等),并调用了onTakePicture @Override public void takePictureSnapshot(final PictureResult.Stub stub) { final boolean metering = mPictureSnapshotMetering; if (isTakingPicture()) return; stub.location = mLocation; stub.isSnapshot = true; stub.facing = mFacing; stub.format = PictureFormat.JPEG; AspectRatio ratio = AspectRatio.of(getPreviewSurfaceSize(Reference.OUTPUT)); onTakePictureSnapshot(stub, ratio, metering); } 3. onTakePictureSnapshot这里给参数封装类stub赋值了一些值,然后初始化Snapshot2PictureRecorder,并调用其take()方法 @Override protected void onTakePictureSnapshot(@NonNull final PictureResult.Stub stub, @NonNull final AspectRatio outputRatio, boolean doMetering) { stub.size = getUncroppedSnapshotSize(Reference.OUTPUT); stub.rotation = getAngles().offset(Reference.VIEW, Reference.OUTPUT, Axis.ABSOLUTE); mPictureRecorder = new Snapshot2PictureRecorder(stub, this, (RendererCameraPreview) mPreview, outputRatio); mPictureRecorder.take(); } 4. Snapshot2PictureRecorder.takeSnapshot2PictureRecorder继承自SnapshotGlPictureRecorder,我们这里直接来看SnapshotGlPictureRecorder.take() public void take() { mPreview.addRendererFrameCallback(new RendererFrameCallback() { @RendererThread public void onRendererTextureCreated(int textureId) { SnapshotGlPictureRecorder.this.onRendererTextureCreated(textureId); } @RendererThread @Override public void onRendererFilterChanged(@NonNull Filter filter) { SnapshotGlPictureRecorder.this.onRendererFilterChanged(filter); } @RendererThread @Override public void onRendererFrame(@NonNull SurfaceTexture surfaceTexture, int rotation, float scaleX, float scaleY) { mPreview.removeRendererFrameCallback(this); SnapshotGlPictureRecorder.this.onRendererFrame(surfaceTexture, rotation, scaleX, scaleY); } }); }这里的mPreview实际上是GlCameraPreview,而通过RendererFrameCallback回调,会触发如下几个方法 onRendererTextureCreated 、onRendererFilterChanged、onRendererFrame 。 4.1 onRendererFilterChanged当重新设置Filter的时候会调用这个回调。onRendererFilterChanged里会将filter拷贝一份,赋值给TextureDrawer protected void onRendererFilterChanged(@NonNull Filter filter) { mTextureDrawer.setFilter(filter.copy()); } 4.2 onRendererFrame当OpenGL绘制的时候,会调用onRendererFrame,onRendererFrame里会调用takeFrame() protected void onRendererFrame(final SurfaceTexture surfaceTexture, final int rotation, final float scaleX, final float scaleY) { final EGLContext eglContext = EGL14.eglGetCurrentContext(); takeFrame(surfaceTexture, rotation, scaleX, scaleY, eglContext); } 5. takeFrame 5.1 创建EGL窗口首先,会创建EGL窗口,这里创建了一个假的,前台不可见的一个EGL窗口,专门用来保存图片 // 0. EGL window will need an output. // We create a fake one as explained in javadocs. final int fakeOutputTextureId = 9999; SurfaceTexture fakeOutputSurface = new SurfaceTexture(fakeOutputTextureId); fakeOutputSurface.setDefaultBufferSize(mResult.size.getWidth(), mResult.size.getHeight()); 5.2 创建EGL Surface接着,来创建EglSurface // 1. Create an EGL surface final EglCore core = new EglCore(eglContext, EglCore.FLAG_RECORDABLE); final EglSurface eglSurface = new EglWindowSurface(core, fakeOutputSurface); eglSurface.makeCurrent(); 5.2.1 EglSurface其中,这个com.otaliastudios.opengl.EglSurface是作者自己创建的,继承自EglNativeSurface,其内部调用了EglCore public expect abstract class EglSurface internal constructor(eglCore: EglCore, eglSurface: EglSurface) : EglNativeSurface public open class EglNativeSurface internal constructor( internal var eglCore: EglCore, internal var eglSurface: EglSurface) { public fun getWidth(): Int { return if (width |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |