如何从 Surface View 获取位图
Posted
技术标签:
【中文标题】如何从 Surface View 获取位图【英文标题】:How to get bitmap from Surface View 【发布时间】:2021-06-29 15:54:31 【问题描述】:我正在尝试从我的表面视图中获取位图。我已经在这个论坛和几乎所有论坛上看到了很多答案。我正在使用 ViewGroup 的自定义类,其中我使用表面视图来预览相机图像和图形叠加。
这是我的 CameraSourcePreview.class
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.SurfaceTexture;
import android.support.v7.util.AsyncListUtil;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.common.images.Size;
import com.google.android.gms.vision.CameraSource;
import java.io.IOException;
public class CameraSourcePreview extends ViewGroup
private static final String TAG = "CameraSourcePreview";
private Context mContext;
private SurfaceView mSurfaceView;
private boolean mStartRequested;
private boolean mSurfaceAvailable;
private CameraSource mCameraSource;
private GraphicOverlay mOverlay;
public CameraSourcePreview(Context context, AttributeSet attrs)
super(context, attrs);
mContext = context;
mStartRequested = false;
mSurfaceAvailable = false;
mSurfaceView = new SurfaceView(context);
mSurfaceView.getHolder().addCallback(new SurfaceCallback());
addView(mSurfaceView);
public void start(CameraSource cameraSource) throws IOException
if (cameraSource == null)
stop();
mCameraSource = cameraSource;
if (mCameraSource != null)
mStartRequested = true;
startIfReady();
public void start(CameraSource cameraSource, GraphicOverlay overlay) throws IOException
mOverlay = overlay;
start(cameraSource);
public void stop()
if (mCameraSource != null)
mCameraSource.stop();
public void release()
if (mCameraSource != null)
mCameraSource.release();
mCameraSource = null;
private void startIfReady() throws IOException
if (mStartRequested && mSurfaceAvailable)
mCameraSource.start(mSurfaceView.getHolder());
if (mOverlay != null)
Size size = mCameraSource.getPreviewSize();
int min = Math.min(size.getWidth(), size.getHeight());
int max = Math.max(size.getWidth(), size.getHeight());
if (isPortraitMode())
// Swap width and height sizes when in portrait, since it will be rotated by
// 90 degrees
mOverlay.setCameraInfo(min, max, mCameraSource.getCameraFacing());
else
mOverlay.setCameraInfo(max, min, mCameraSource.getCameraFacing());
mOverlay.clear();
mStartRequested = false;
private class SurfaceCallback implements SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder surface)
mSurfaceAvailable = true;
try
startIfReady();
catch (IOException e)
Log.e(TAG, "Could not start camera source.", e);
@Override
public void surfaceDestroyed(SurfaceHolder surface)
mSurfaceAvailable = false;
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
int width = 320;
int height = 240;
if (mCameraSource != null)
Size size = mCameraSource.getPreviewSize();
if (size != null)
width = size.getWidth();
height = size.getHeight();
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode())
int tmp = width;
width = height;
height = tmp;
final int layoutWidth = right - left;
final int layoutHeight = bottom - top;
// Computes height and width for potentially doing fit width.
int childWidth = layoutWidth;
int childHeight = layoutHeight;
//(int)(((float) layoutWidth / (float) width) * height);
/*
// If height is too tall using fit width, does fit height instead.
if (childHeight > layoutHeight)
childHeight = layoutHeight;
childWidth = (int)(((float) layoutHeight / (float) height) * width);
*/
for (int i = 0; i < getChildCount(); ++i)
getChildAt(i).layout(0, 0, childWidth, childHeight);
try
startIfReady();
catch (IOException e)
Log.e(TAG, "Could not start camera source.", e);
private boolean isPortraitMode()
int orientation = mContext.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE)
return false;
if (orientation == Configuration.ORIENTATION_PORTRAIT)
return true;
Log.d(TAG, "isPortraitMode returning false by default");
return false;
现在,当我从 CameraSource 捕捉图像时,它会捕捉图像,但不会捕捉我在表面视图上膨胀的图形叠加层。表面视图也不允许我从中获取位图。如果我尝试获取根视图的屏幕截图,则它仅捕获图形叠加而不是表面视图图像。
我的应用程序正在处理面部过滤器 github 项目的逻辑(将根据要求提供链接) 我基本上被卡住了,因为我想同时捕获两者。
【问题讨论】:
【参考方案1】:您必须截取特定的视图屏幕截图,例如以这种方式将任何视图转换为位图
How to convert Views to bitmaps?
【讨论】:
我尝试截取表面视图。但它只捕获图形覆盖而不是人的图片。以上是关于如何从 Surface View 获取位图的主要内容,如果未能解决你的问题,请参考以下文章