Android 相机预览 capture/resizing 捕获的图像以匹配预览
Android camera preview capture/resizing captured image to match preview
我正在尝试创建一个应用程序,它要求我拍摄之前拍摄的图像并将其放置在当前相机预览中,透明度约为 0.5。此 "overlay" 图像用作拍摄下一张照片的指南;客户端将使用叠加层将预览中的当前帧与先前捕获的图像进行比较。解决此问题的一种简单方法是检索捕获的最后一个文件并将其设置为视图。但是,捕获的图像并不总是与相机预览分辨率和纵横比匹配,导致叠加和预览在对象表示方面不匹配(同一对象在预览和捕获图像之间的大小可能不同)。我试过:
- 使用Camera Preview回调存储当前帧数据,效率低下且效果不佳(也有轻微的翻译,尺寸准确)
- 使用前面提到的上一个文件方法并尝试相应地缩小或放大,匹配宽高比(也许我的数学错误[我使用预览的宽高比来计算原始图像中的面积]和仍然可以使用这种方法吗?如果有人能参与进来,我们将不胜感激。
- 研究捕获表面视图内容的方法,但无济于事。
目前,我想深入了解我将如何处理的两种可能方法是:
- 以某种方式冻结 SurfaceView(锁定某种 canvas),设置不透明度并使用另一个 SurfaceView 来显示相机(可能是低效、笨拙的解决方法?)。
- 调用 PictureCallback 时捕获 SurfaceView 的内容并存储在位图中(首选)。
当然,如有任何其他建议,我们将不胜感激。
注意:也有类似的问题,我花了几个小时来研究它们,但其中 none 正确地解决了我的问题或提供了足够的细节。
我使用两个 TextureView 组件让它工作:
- 一个设置为 0.5 alpha 并使用 RelativeLayout 放置在另一个之上。
- 让不透明的 TextureView 注册一个 SurfaceTextureListener
- 在所述侦听器中启动由 onSurfaceTextureAvailable 触发的相机
- 将给定的 SurfaceTexture 设置为 previewTexture
- 按下按钮时,在透明 TextureView
的 canvas 上绘制 getBitmap()
Activity.java(实现 SurfaceTextureListener):
@Override
public void onClick(View view) {
{
Canvas canvas = alphaCameraTextureView.lockCanvas();
canvas.drawBitmap( cameraTextureView.getBitmap(), 0, 0, null );
alphaCameraTextureView.unlockCanvasAndPost( canvas );
}
@Override
public void onSurfaceTextureAvailable( SurfaceTexture surfaceTexture, int width, int height )
{
try
{
camera = Camera.open();
camera.setDisplayOrientation( 90 );
camera.setPreviewTexture( surfaceTexture );
camera.startPreview();
}
catch (IOException e ) { e.printStackTrace(); }
}
@Override
public boolean onSurfaceTextureDestroyed( SurfaceTexture surfaceTexture )
{
camera.stopPreview();
camera.release();
return false;
}
TextureViews 在 layout.xml:
<TextureView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/cameraTextureView"
android:layout_weight="0"/>
<TextureView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/alphaCameraTextureView"
android:alpha="0.5"
android:layout_weight="0" />
我正在尝试创建一个应用程序,它要求我拍摄之前拍摄的图像并将其放置在当前相机预览中,透明度约为 0.5。此 "overlay" 图像用作拍摄下一张照片的指南;客户端将使用叠加层将预览中的当前帧与先前捕获的图像进行比较。解决此问题的一种简单方法是检索捕获的最后一个文件并将其设置为视图。但是,捕获的图像并不总是与相机预览分辨率和纵横比匹配,导致叠加和预览在对象表示方面不匹配(同一对象在预览和捕获图像之间的大小可能不同)。我试过:
- 使用Camera Preview回调存储当前帧数据,效率低下且效果不佳(也有轻微的翻译,尺寸准确)
- 使用前面提到的上一个文件方法并尝试相应地缩小或放大,匹配宽高比(也许我的数学错误[我使用预览的宽高比来计算原始图像中的面积]和仍然可以使用这种方法吗?如果有人能参与进来,我们将不胜感激。
- 研究捕获表面视图内容的方法,但无济于事。
目前,我想深入了解我将如何处理的两种可能方法是:
- 以某种方式冻结 SurfaceView(锁定某种 canvas),设置不透明度并使用另一个 SurfaceView 来显示相机(可能是低效、笨拙的解决方法?)。
- 调用 PictureCallback 时捕获 SurfaceView 的内容并存储在位图中(首选)。
当然,如有任何其他建议,我们将不胜感激。
注意:也有类似的问题,我花了几个小时来研究它们,但其中 none 正确地解决了我的问题或提供了足够的细节。
我使用两个 TextureView 组件让它工作:
- 一个设置为 0.5 alpha 并使用 RelativeLayout 放置在另一个之上。
- 让不透明的 TextureView 注册一个 SurfaceTextureListener
- 在所述侦听器中启动由 onSurfaceTextureAvailable 触发的相机
- 将给定的 SurfaceTexture 设置为 previewTexture
- 按下按钮时,在透明 TextureView 的 canvas 上绘制 getBitmap()
Activity.java(实现 SurfaceTextureListener):
@Override
public void onClick(View view) {
{
Canvas canvas = alphaCameraTextureView.lockCanvas();
canvas.drawBitmap( cameraTextureView.getBitmap(), 0, 0, null );
alphaCameraTextureView.unlockCanvasAndPost( canvas );
}
@Override
public void onSurfaceTextureAvailable( SurfaceTexture surfaceTexture, int width, int height )
{
try
{
camera = Camera.open();
camera.setDisplayOrientation( 90 );
camera.setPreviewTexture( surfaceTexture );
camera.startPreview();
}
catch (IOException e ) { e.printStackTrace(); }
}
@Override
public boolean onSurfaceTextureDestroyed( SurfaceTexture surfaceTexture )
{
camera.stopPreview();
camera.release();
return false;
}
TextureViews 在 layout.xml:
<TextureView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/cameraTextureView"
android:layout_weight="0"/>
<TextureView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/alphaCameraTextureView"
android:alpha="0.5"
android:layout_weight="0" />