Android Custom Camera(2)

Through the introduction of an Android custom Camera (一), we have been able to complete a camera based on the demo, of course, there are a lot of attention to the details of the problem, such as the preview direction, set the preview ratio and return the proportion of pictures and so on , The details can see previous blog, this time I will enrich the camera’s function to join the flash mode, square shooting, delay shooting and front and rear camera switching function, then one by one to start it. (There will be a complete source address below).

Flash mode

The camera’s flash mode there are three, automatic, close, open, the code is also better understand, before the camera can switch calls. Note I added a note in code below:

/**
     * turnLightOff
     *
     * @param mCamera
     */
    public void turnLightOff(Camera mCamera) {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (parameters == null) {
            return;
        }
        List<String> flashModes = parameters.getSupportedFlashModes();
        String flashMode = parameters.getFlashMode();
        // Check if camera flash exists
        if (flashModes == null) {
            return;
        }
        if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)) {
            // Turn off the flash
            if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
            } else {
            }
        }
    }

2 automatic mode:

/**
     * turnLightAuto
     *
     * @param mCamera
     */
    public void turnLightAuto(Camera mCamera) {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (parameters == null) {
            return;
        }
        List<String> flashModes = parameters.getSupportedFlashModes();
        // Check if camera flash exists
        if (flashModes == null) {
            // Use the screen as a flashlight (next best thing)
            return;
        }
        String flashMode = parameters.getFlashMode();
        if (!Camera.Parameters.FLASH_MODE_AUTO.equals(flashMode)) {
            // Turn on the flash
            if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
            } else {
            }
        }
    }

3 open

 @param mCamera
     */
    public void turnLightOn(Camera mCamera) {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (parameters == null) {
            return;
        }
        List<String> flashModes = parameters.getSupportedFlashModes();
        // Check if camera flash exists
        if (flashModes == null) {
            // Use the screen as a flashlight (next best thing)
            return;
        }
        String flashMode = parameters.getFlashMode();
        if (!Camera.Parameters.FLASH_MODE_ON.equals(flashMode)) {
            // Turn on the flash
            if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
            } else {
            }
        }
    }

Square shot

Here I want to talk about how I do, at present I think because we look at the proportion of framing frames must meet the size of mobile phone support, there are surfaceView and preview the proportion of the same size, so that we can not determine the size of the frame is specific How many, so I achieved a square shot with the way to cover the viewfinder frame, shooting time frame will be covered into a square, in the back of the picture and then cut it into a square can be, in the current project I also In this way, because many mobile phones are directly supporting the square size, where I used two attribute animation to cover the viewfinder, the code is as follows, here is to calculate the height to cover.

/**
     * camera_square
     */
    public void camera_square_0() {
        camera_square.setImageResource(R.drawable.btn_camera_size1_n);

        ValueAnimator anim = ValueAnimator.ofInt(0, animHeight);
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentValue = Integer.parseInt(animation.getAnimatedValue().toString());
                RelativeLayout.LayoutParams Params = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                Params.setMargins(0, SystemUtils.dp2px(context, 44), 0, 0);
                homeCustom_cover_top_view.setLayoutParams(Params);

                RelativeLayout.LayoutParams bottomParams = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                bottomParams.setMargins(0, screenHeight - menuPopviewHeight - currentValue, 0, 0);
                homeCustom_cover_bottom_view.setLayoutParams(bottomParams);
            }

        });
        anim.start();

        homeCustom_cover_top_view.bringToFront();
        home_custom_top_relative.bringToFront();
        homeCustom_cover_bottom_view.bringToFront();
        index++;
    }

    public void camera_square_1() {
        camera_square.setImageResource(R.drawable.btn_camera_size2_n);

        ValueAnimator anim = ValueAnimator.ofInt(animHeight, 0);
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentValue = Integer.parseInt(animation.getAnimatedValue().toString());
                RelativeLayout.LayoutParams Params = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                Params.setMargins(0, SystemUtils.dp2px(context, 44), 0, 0);
                homeCustom_cover_top_view.setLayoutParams(Params);

                RelativeLayout.LayoutParams bottomParams = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                bottomParams.setMargins(0, screenHeight - menuPopviewHeight - currentValue, 0, 0);
                homeCustom_cover_bottom_view.setLayoutParams(bottomParams);
            }
        });
        anim.start();
        index = 0;
    }

Delayed shooting

First of all, say the principle of delay shooting, in fact, more than one way to achieve, where I use the thread plus the way the main code is as follows, first recorded a delay time, and then decrement this time every 1s, and finally it is equal to 0 When the implementation of the shooting code, the effect I will not paste it, you can download the code to run to see, that is, a large number of seconds on the screen

new Thread(new Runnable() {
                            @Override
                            public void run() {
                                while (delay_time > 0) {
                                    //Count in seconds
                                    try {
                                        Thread.sleep(1000);
                                    } catch (InterruptedException e) {
                                        mHandler.sendEmptyMessage(AppConstant.WHAT.ERROR);
                                        return;
                                    }
                                    delay_time--;
                                    mHandler.sendEmptyMessage(AppConstant.WHAT.SUCCESS);
                                }
                            }
                        }).start();

Switch the front rear camera

Almost all of the camera program needs this function, must be able to front and rear ah, that in fact, this is also relatively simple to achieve, when the camera is in the process of previewing before and after the switch must first release the camera resources, and then And then open the preview, switch the camera is nothing more than switch cameraId, here look at the next code:

 public void  switchCamera() {
        releaseCamera();
        //This method getNumberOfCameras () is introduced from the API Level 9, get the number of cameras in the normal normal mobile phone only one camera, here I also follow a camera to deal with the
        mCameraId = (mCameraId + 1) % mCamera.getNumberOfCameras();
        mCamera = getCamera(mCameraId);
        if (mHolder != null) {
            startPreview(mCamera, mHolder);
        }
    }

Add watermark

The way to say that the function of the watermark it, plus watermark function is not difficult to achieve, it is rare to draw a good watermark, in fact, watermark is also in the camera to return to the bitmap to join, in fact, is painted with Canvas class, the core The code is as follows, assuming the camera returns the picture shown as bitmap:

Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(tempbitmap, left, top, paint);

Code is generally the case, through the canvas.drawBitmap method to draw up, of course, I am free to draw the position. But you record the location of the watermark when previewing, and then painted up properly.

The following is the source address:

https://github.com/jinguangyue/CustomCamera

Advertisements

Android custom Camera (1)

Get the camera and release the camera

First of all, there can only be a camera instance, after the camera must be released, then it also has its own life cycle, first get the camera, where an ID, this id can be set before the camera and rear camera, behind the blog I will join Code.

/**
     * getCamera
     * @return
     */
    private Camera getCamera(int id){
        Camera camera = null;
        try{
            camera = Camera.open(id);
        }catch (Exception e){

        }
        return camera;
    }

/**
     * releaseCamera
     */
    private void releaseCamera(){
        if(mCamera != null){
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

Use the release of the camera after the use of resources, here is a reason to write, one step can not be less, I sometimes forget to write mCamera.setPreviewCallback (null);

Because the camera to real-time preview, that ordinary View can not meet the requirements of the drawing, and here to use a double buffer mechanism SurfaceView, the following we have to do is to Camera and SurfaceView binding, it needs another class The SurfaceHolder.

Here is a special mention of CameraUtil.getInstance (). SetCameraDisplayOrientation (this, mCameraId, camera);

I will write the source address, because the default preview of the Android system are horizontal, the basic operation is camera.setDisplayOrientation (90); direct rotation 90 degrees correction, but I was in the development of some mobile phones on the preview Came, and finally use this method to solve, and its basic principle is that some of the bottom of the mobile phone system on the preview of the preview, and some did not, that can be judged by the cameraInfo. SO this perfect solution to my problem, hope can help you:

/**
     * Preview
     */
    private void startPreview(Camera camera, SurfaceHolder holder){
        try {
      
            setupCamera(camera);
            camera.setPreviewDisplay(holder);
           
            CameraUtil.getInstance().setCameraDisplayOrientation(this, mCameraId, camera);
//            camera.setDisplayOrientation(90);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Set the SurfaceHolder

surfaceView = (SurfaceView)findViewById(R.id.surfaceView);
        mHolder = surfaceView.getHolder();
        mHolder.addCallback(this);

Where SurfaceHolder wants to add a callback method to see the comment:

@Override
    public void surfaceCreated(SurfaceHolder holder) {
    //Open the camera preview when the surface is created
        startPreview(mCamera, holder);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    //Call this method when the camera changes, at which point you should stop previewing and then restart
        mCamera.stopPreview();
        startPreview(mCamera, holder);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    //Release the camera resources when destroy
        releaseCamera();
    }

Here to elaborate on the setCamera method, without this method can also be a normal preview, but this method to set the camera’s preview size, return to the picture size, in particular, note that the preview size returns the size of the picture and the size of the surfaceView ratio Must be the same, or else the program crashes, see the code below

/**
     * Setting
     */
    private void setupCamera(Camera camera) {
        Camera.Parameters parameters = camera.getParameters();

        List<String> focusModes = parameters.getSupportedFocusModes();
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            // Autofocus mode is supported auto focus
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }

        //Where the third parameter is the smallest size getPropPreviewSize Method will remove the minimum size of all supported sizes from the minimum size to the ascending order
        Camera.Size previewSize = CameraUtil.getInstance().getPropPreviewSize(parameters.getSupportedPreviewSizes(), 1000);
        parameters.setPreviewSize(previewSize.width, previewSize.height);

        Camera.Size pictrueSize = CameraUtil.getInstance().getPropPictureSize(parameters.getSupportedPictureSizes(), 1000);
        parameters.setPictureSize(pictrueSize.width, pictrueSize.height);

        camera.setParameters(parameters);

        Log.d("previewSize.width===", previewSize.width + "");
        Log.d("previewSize.height===", previewSize.height + "");

        /**
         * Set the size of the surfaceView Because the camera default is horizontal screen, so get the support size are also horizontal screen size
         * We in the startPreview method inside it correction over, but here we set the size of the surfaceView to pay attention to the time previewSize.height<previewSize.width
       
         * The general camera is the width of the screen here set to the screen width height adaptive you can also set the size you want
         */
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(screenWidth, screenWidth * previewSize.width/previewSize.height);
        //Here, of course, you can set the camera position, such as the center of the top here
        //params.gravity = Gravity.CENTER;
        surfaceView.setLayoutParams(params);
    }

There is also a place to pay special attention to is that you set the preview size and return the image size must be the current size of the phone support.

Here through getPropPictureSize and getPropPreviewSize get all the phone support the size of .the default camera preview are horizontal screen.
Here you can set a minimum preview width of 1000, as long as more than 1000 support size can be. Here is the last step is also very important, that is, Camera’s life cycle must be bound with the current Activity, so we do so:

@Override
    protected void onResume() {
        super.onResume();
        if(mCamera == null){
            mCamera = getCamera(mCameraId);
            if(mHolder != null){
                startPreview(mCamera, mHolder);
            }
        }
    }

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

Here in the Activity to display when you start the camera preview, in the Activity onPause when the release of the camera resources on it. It can now preview can also take pictures wow, then take a camera method.

private void captrue() {
        mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                //Convert data to a bitmap or you can save it directly as a file FileOutputStream
                //Here I believe that most of the other useful to add a watermark, such as follow-up and then explain
               Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
               CameraUtil.getInstance().setTakePicktrueOrientation(mCameraId, bitmap);
                //Where you can see the width of the print CameraUtil.getInstance().getPropPictureSize(parameters.getSupportedPictureSizes(), 200);
                // The minimum width of this setting affects the size of the returned picture so it is generally here that is around 1000
                Log.d("bitmapWidth==", bitmap.getWidth() + "");
                Log.d("bitmapHeight==", bitmap.getHeight() + "");
            }
        });
    }

Here we have a place to say that the above we have made a preview of the preview, that generated the picture we have to correct back ah, the implementation of CameraUtil.getInstance (). SetTakePicktrueOrientation (mCameraId, bitmap); of course, through Android.hardware.Camera. CameraInfo to operate.

The following is the source address:

https://github.com/jinguangyue/CustomCamera