在android中,将相机预览流到视图上

2024-05-23

我想将 Android 相机的相机预览流式传输到视图上。目的是随后使用 onDraw() 将各种内容添加到视图中。我不需要随时实际捕捉图像。 它不必是最高质量或每秒最大数量的帧。 有谁知道如何做到这一点?


将其添加到您的 xml 中:

<SurfaceView
    android:id="@+id/camerapreview"  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
/>

进入你的活动类别:

private Preview mPreview;
Camera mCamera;
int numberOfCameras;
int cameraCurrentlyLocked;
int defaultCameraId;

onCreate方法:

mPreview = new Preview(this);
setContentView(mPreview);

mPreview.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        mCamera.autoFocus(null);
    }
});

@Override
protected void onPause() {
    super.onPause();

    // Because the Camera object is a shared resource, it's very
    // important to release it when the activity is paused.
    if (mCamera != null) {
        mPreview.setCamera(null);
        mCamera.release();
        mCamera = null;
    }
}

@Override
protected void onResume() {
    super.onResume();

    // Open the default i.e. the first rear facing camera.
    mCamera = Camera.open();
    cameraCurrentlyLocked = defaultCameraId;
    mPreview.setCamera(mCamera);
}

和预览类:

public class Preview extends ViewGroup implements SurfaceHolder.Callback {
    private final String TAG = "Preview";

    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;
    Size mPreviewSize;
    List<Size> mSupportedPreviewSizes;
    Camera mCamera;

    public Preview(Context context) {
        super(context);

        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void setCamera(Camera camera) {
        mCamera = camera;
        if (mCamera != null) {
            mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
            requestLayout();
        }
    }

    public void switchCamera(Camera camera) {
       setCamera(camera);
       try {
           camera.setPreviewDisplay(mHolder);
       } catch (IOException exception) {
           Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
       }
       Camera.Parameters parameters = camera.getParameters();
       parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
       requestLayout();

       camera.setParameters(parameters);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // We purposely disregard child measurements because act as a
        // wrapper to a SurfaceView that centers the camera preview instead
        // of stretching it.
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed && getChildCount() > 0) {
            final View child = getChildAt(0);

            final int width = r - l;
            final int height = b - t;

            int previewWidth = width;
            int previewHeight = height;
            if (mPreviewSize != null) {
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
            }

            // Center the child SurfaceView within the parent.
            if (width * previewHeight > height * previewWidth) {
                final int scaledChildWidth = previewWidth * height / previewHeight;
                child.layout((width - scaledChildWidth) / 2, 0,
                        (width + scaledChildWidth) / 2, height);
            } else {
                final int scaledChildHeight = previewHeight * width / previewWidth;
                child.layout(0, (height - scaledChildHeight) / 2,
                        width, (height + scaledChildHeight) / 2);
            }
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
            }
        } catch (IOException exception) {
            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }


    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        if(mCamera != null){
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
            requestLayout();

            mCamera.setParameters(parameters);
            mCamera.startPreview();
        }
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在android中,将相机预览流到视图上 的相关文章

随机推荐

  • 在后台运行 URL 请求

    我想在一定的时间间隔内发出 url 请求 例如 每 10 分钟应用程序应该发出一次 url 调用并获取一些 json 数据 应用程序在后台运行时应该能够执行此操作 这可以做到吗 如果是这样 这是否违反 Apple 服务条款 有什么限制吗 i
  • Scala UpperBound 和 LowerBound 概念

    下面是我尝试运行的代码 class Student def printDetails println I am a student def printSomeOtherDetails println I love Studying clas
  • iPhone 和 iPad 滚动结束

    我正在制作一些无限滚动的 jQuery 跨浏览器画廊 我工作得很好 但在 iPhone 上 我想也在 iPad 上 而不是相等的值 我有一些不成比例的值不匹配 window scrollTop document height window
  • 使用 Qt 的网络服务

    我正在寻找使用 Qt 服务器端 实现 Web 服务的代码 如果您有任何信息 我将不胜感激 Regards 您可以使用libqxt http libqxt bitbucket org doc 0 6 qxtweb html实现服务器端Web服
  • 如何使用 SharedPreferences 保存多个值?

    我正在开发一个字典应用程序 在我的应用程序中 我假设用户想要保存最喜欢的单词 我决定使用共享首选项保存这些值 我知道 SQLite 和文件更好 但我坚持使用 SharedPreferences 所以继续使用它 下面是我的代码 Overrid
  • 是否可以从 servlet 内部以编程方式设置请求上下文路径?

    这是一个特殊情况 我陷入了处理 企业 网络应用程序的困境 企业应用程序正在调用request getContext 并将其与另一个字符串进行比较 我发现我可以使用 getServletContext getContextPath 获取 se
  • 无法在 selenium 和 requests 之间传递 cookie,以便使用后者进行抓取

    我用 python 结合 selenium 编写了一个脚本来登录网站 然后从driver to requests这样我就可以继续使用requests进行进一步的活动 I used item soup select one div class
  • 为什么我需要使用 setState 回调来设置依赖于第一个项目的 setState 完成的第二个状态项目的状态?

    在此 componentDidUpdate 方法中 执行 setState 将引号设置为从 fetch 返回的内容后 我必须使用回调再次执行 setState 将 randomQuoteIndex 设置为调用 randomQuoteInde
  • 使用 DirectCast、CType、TryCast 转换数据类型

    自从我在 2005 年从 VB6 迁移到 VB NET 以来 我一直在使用 CType 将一种数据类型转换为另一种数据类型 我这样做是因为它打字速度更快 以前存在于 VB6 中 而且我不知道为什么我必须使用 DirectCast 如果它们之
  • 使用链表进行堆排序

    我想知道是否有人曾经使用链表进行堆排序 如果他们可以提供代码 我已经能够使用数组进行堆排序 但尝试在链表中进行排序似乎不切实际 而且在你知道的地方很痛苦 我必须为我正在做的项目实现链接列表 任何帮助将不胜感激 我也用C 答案是 你不想在链表
  • ANCESTOR 查询解析错误:使用 DISTINCT

    不是这个问题 祖先查询解析错误 https stackoverflow com questions 15463964 ancestor query parse error 我用 IS 正确地构造了它 SELECT DISTINCT batc
  • 实体框架、LinqToSQL 和 sql 注入

    完全使用 Linq To SQL 或实体框架的项目是否有可能遭受 SQL 注入 我认为这可能不是因为 ORM 生成的 SQL 应该是免 SQL 注入的 但我不确定 当您按预期使用这些框架时 即直接使用实体 表 那么就不会 所有字符串比较 即
  • 如何将 SCNPlane 颜色更改为透明颜色

    我正在开发一个 ARKit 项目 在水平面上点击时需要波纹动画效果 为此 我采用了 UIView 对象并将其作为 SCNPlane 对象材料的内容传递 我已将波纹动画添加到 UIView 对象 一切正常 但我无法将 SCNPlane 颜色更
  • 节点 sass 无效 CSS

    node sass 是否支持 use 由于我收到此错误 SassError t family fonts 之后的 CSS 无效 预期的表达式 例如 1px 粗体 为 roboto 这是 Nav scss 的代码 nav width 100
  • 如何按时间间隔翻转div

    您好 请看这个脚本并告诉我如何按时间间隔翻转 A B 和 C div 我希望A先翻转然后停止 B接下来翻转并停止 然后C然后再次回到A B和C 就像循环一样 然后重新开始 这在 CSS3 中可能吗 在此代码中 所有 div 同时翻转 HOL
  • 在 UIWebView 中禁用复制和粘贴

    几乎 我已经尝试了一切方法来禁用复制 粘贴UIWebView但对我来说没有任何作用 我正在加载我的UIWebView来自字符串 字符串数组 如下所示 webView loadHTMLString NSString stringWithFor
  • LEFT JOIN 比 INNER JOIN 快得多

    我有一张桌子 MainTable 有超过 600 000 条记录 它通过第二个表连接到自身 JoinTable 在父 子类型关系中 SELECT Child ID Parent ID FROM MainTable AS Child JOIN
  • Monkeyrunner/jython 中未找到 JDBC 驱动程序错误

    我需要在中插入一些东西DB 我在用着JDBC as a connector jython the script mysql数据库和脚本正在运行CentOS 我的代码看起来像这样 from com android monkeyrunner i
  • 是否可以通过 Android 应用程序来录音?

    我是一名开发人员 希望创建一个 Android 应用程序来记录电话 这是出于我个人的需要 为了我自己的目的和记录而记录电话 是否有可能做到这一点 是否可以访问麦克风以及通过扬声器发出的声音 我对 Android 开发有点陌生 所以请耐心等待
  • 在android中,将相机预览流到视图上

    我想将 Android 相机的相机预览流式传输到视图上 目的是随后使用 onDraw 将各种内容添加到视图中 我不需要随时实际捕捉图像 它不必是最高质量或每秒最大数量的帧 有谁知道如何做到这一点 将其添加到您的 xml 中