【问题标题】:in android, stream camera preview onto a view在 android 中,将相机预览流式传输到视图中
【发布时间】:2012-07-29 18:16:06
【问题描述】:

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

【问题讨论】:

    标签: android view camera


    【解决方案1】:

    将此添加到您的 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();
            }
        }
    
    }
    

    【讨论】:

    • 好的,会试试的。然后我可以访问它的 onDraw() 功能并添加东西吗?
    • 我几乎不记得问过这个(或解决方案),但 4 个竖起大拇指表示您的解决方案是正确的。所以谢谢!
    • 您不需要或使用 XML 部分
    猜你喜欢
    • 2018-07-16
    • 1970-01-01
    • 2013-01-26
    • 2018-05-21
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多