Android 中的相机预览不是全屏

问题描述 投票:0回答:2

我正在尝试获取相机预览并在 onPreviewFrame() 中更改它并将其显示给用户。我已经实现了所需的功能,但问题在于相机预览的大小。它总是占用屏幕的较小部分,我想将其设为全屏,即想要拍摄应填充设备整个屏幕的相机预览。我有阅读并尝试了网上可用的任何解决方案,但它们都不适用于我的情况。这是 Surface View 类:

public class MySurfaceView extends SurfaceView implements Callback, Camera.PreviewCallback, android.view.SurfaceHolder.Callback {

    private static final String TAG = "MySurfaceView";
    private int width;
    private int height;
    public SurfaceHolder mHolder;
    private Camera mCamera;
    private int[] rgbints;
    private int mMultiplyColor;

    public MySurfaceView(Context context, AttributeSet attrs , Camera camera , 
            int width , int height) 
    {
        super(context, attrs);

        mCamera = camera;

        this.width = width;
        this.height = height;

        mHolder = getHolder();
        mHolder.addCallback(this);

        mMultiplyColor = getResources().getColor(R.color.honeydew);
    }


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        synchronized (this) {
            this.setWillNotDraw(false); // This allows us to make our own draw calls to this canvas

            rgbints = new int[width * height];

            // try { mCamera.setPreviewDisplay(holder); } catch (IOException e)
            // { Log.e("Camera", "mCamera.setPreviewDisplay(holder);"); }

            mCamera.startPreview();
            mCamera.setPreviewCallback(this);

        }
    }


    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        synchronized (this) {
            try
            {
                CameraActivity cameraActivity = new CameraActivity();
                cameraActivity.releaseCamera();
                cameraActivity = null;
            } catch (Exception e) {
                Log.e("Camera", e.getMessage());
            }
        }
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        Canvas canvas = null;

        if (mHolder == null) 
        {
            return;
        }

        try {
            synchronized (mHolder) 
            {
                canvas = mHolder.lockCanvas(null);

                int canvasWidth = canvas.getWidth();
                int canvasHeight = canvas.getHeight();

                decodeYUV(rgbints, data, width, height);

                // draw the decoded image, centered on canvas
                canvas.drawBitmap(rgbints, 0, width, canvasWidth-((width+canvasWidth)>>1), canvasHeight-((height+canvasHeight)>>1), width, height, false, null);

                // use some color filter
                canvas.drawColor(mMultiplyColor, Mode.MULTIPLY);

            }
        }  catch (Exception e){
            e.printStackTrace();
        } finally {
            // do this in a finally so that if an exception is thrown
            // during the above, we don't leave the Surface in an
            // inconsistent state
            if (canvas != null)
            {
                mHolder.unlockCanvasAndPost(canvas);
                canvas = null;
            }
        }
    }


    public void decodeYUV(int[] out, byte[] fg, int width, int height) throws NullPointerException, IllegalArgumentException {
        int sz = width * height;
        if (out == null)
            throw new NullPointerException("buffer out is null");
        if (out.length < sz)
            throw new IllegalArgumentException("buffer out size " + out.length + " < minimum " + sz);
        if (fg == null)
            throw new NullPointerException("buffer 'fg' is null");
        if (fg.length < sz)
            throw new IllegalArgumentException("buffer fg size " + fg.length + " < minimum " + sz * 3 / 2);
        int i, j;
        int Y, Cr = 0, Cb = 0;
        for (j = 0; j < height; j++) {
            int pixPtr = j * width;
            final int jDiv2 = j >> 1;
        for (i = 0; i < width; i++) {
            Y = fg[pixPtr];
            if (Y < 0)
                Y += 255;
            if ((i & 0x1) != 1) {
                final int cOff = sz + jDiv2 * width + (i >> 1) * 2;
                Cb = fg[cOff];
                if (Cb < 0)
                    Cb += 127;
                else
                    Cb -= 128;
                Cr = fg[cOff + 1];
                if (Cr < 0)
                    Cr += 127;
                else
                    Cr -= 128;
            }
            int R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
            if (R < 0)
                R = 0;
            else if (R > 255)
                R = 255;
            int G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5);
            if (G < 0)
                G = 0;
            else if (G > 255)
                G = 255;
            int B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
            if (B < 0)
                B = 0;
            else if (B > 255)
                B = 255;
            out[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R;
        }
        }

    }

    public void showSupportedCameraFormats(Parameters p) {
        List<Integer> supportedPictureFormats = p.getSupportedPreviewFormats();
        Log.d(TAG, "preview format:" + cameraFormatIntToString(p.getPreviewFormat()));
        for (Integer x : supportedPictureFormats) {
            Log.d(TAG, "suppoterd format: " + cameraFormatIntToString(x.intValue()));
        }

    }

    @SuppressWarnings("deprecation")
    private String cameraFormatIntToString(int format) {
        switch (format) {
        case PixelFormat.JPEG:
            return "JPEG";
        case PixelFormat.YCbCr_420_SP:
            return "NV21";
        case PixelFormat.YCbCr_422_I:
            return "YUY2";
        case PixelFormat.YCbCr_422_SP:
            return "NV16";
        case PixelFormat.RGB_565:
            return "RGB_565";
        default:
            return "Unknown:" + format;

        }
    }
}

这是调用者类:

public class CameraActivity extends Activity {

    private Camera mCamera;
    private MySurfaceView surfaceView;
    private RelativeLayout relativeLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        releaseCamera();
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();

        releaseCamera();
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();

        mCamera = Camera.open();

        Camera.Parameters p = mCamera.getParameters();
        Size size = p.getPreviewSize();
        int width = size.width;
        int height = size.height;
        p.setPreviewFormat(ImageFormat.JPEG);
        mCamera.setParameters(p);


        surfaceView = new MySurfaceView(this, null , mCamera ,width , height);

        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

        surfaceView.setLayoutParams(layoutParams);

        relativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);

        relativeLayout.addView(surfaceView);

        surfaceView.showSupportedCameraFormats(p);
    }

    public void releaseCamera()
    {
        if (mCamera != null)
        {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            surfaceView.getHolder().removeCallback(surfaceView);
            mCamera.release();        // release the camera for other applications
            mCamera = null;

            surfaceView.mHolder.removeCallback(surfaceView);
            surfaceView.mHolder = null;

            surfaceView = null;

            relativeLayout.removeAllViews();
            relativeLayout.removeAllViewsInLayout();
            relativeLayout = null;
        }

    }
}

请帮助我。提前致谢。

编辑:

Xml 是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/relativeLayout"    
    android:layout_height="match_parent" >

</RelativeLayout>
android android-camera
2个回答
2
投票

relativelayout 倾向于采用 Linearlayout 并在其中放入framelayout:

<FrameLayout
            android:id="@+id/preview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1" >
        </FrameLayout>

然后在其中设置camerapreview:

surfaceView = new MySurfaceView(this, null , mCamera ,width , height);

((FrameLayout) findViewById(R.id.preview)).addView(surfaceView);

相机预览.java

class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "Preview";

    SurfaceHolder mHolder;
    public Camera camera;

    CameraPreview(Context context) {
        super(context);

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

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.

        if(camera == null){
        camera = Camera.open();


        camera.setDisplayOrientation(90);
        try {
            camera.setPreviewDisplay(holder);


            camera.setPreviewCallback(new PreviewCallback() {

                public void onPreviewFrame(byte[] data, Camera arg1) {

                        CameraPreview.this.invalidate();
                }
            });
        } catch (IOException e) {
           camera.release();
           camera = null;
        }
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        if(camera!=null){
            camera.stopPreview();
            camera.setPreviewCallback(null);

            camera.release();
            camera = null;
        }

    }

    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.
        Camera.Parameters parameters = camera.getParameters();
//        parameters.setPreviewSize(w, h);
        camera.setParameters(parameters);
        camera.startPreview();
    }

    @Override
    public void draw(Canvas canvas) {
            super.draw(canvas);
            Paint p= new Paint(Color.RED);
            Log.d(TAG,"draw");
            canvas.drawText("PREVIEW", canvas.getWidth()/2, canvas.getHeight()/2, p );
    }

    public void releaseCameraAndPreview() {
         if (camera != null) {
            camera.release();
            camera = null;
        }
    }
}

0
投票

就我而言,我通过将这一行

android:hardwareAccelerated="true"
添加到
captureActivity
文件中的
AndroidManifest.xml
来解决问题,因此您可以尝试这种方法。

这是我在

activity_capture.xml
中的预览视图:

<androidx.camera.view.PreviewView
    android:id="@+id/preview"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

这是

CaptureActivity
AndroidManifest.xml
的标签:“

<activity
        android:name=".view.CaptureActivity"
        android:exported="false"
        android:hardwareAccelerated="true" />
© www.soinside.com 2019 - 2024. All rights reserved.