zoukankan      html  css  js  c++  java
  • ActivityCapture

    Index: ActivityCapture.java
    ===================================================================
    --- ActivityCapture.java    (revision 0)
     ActivityCapture.java    (revision 3)
    @@ -0,0 +1,638 @@
    package com.cn.commoncamera;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.content.res.Configuration;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Matrix;
    import android.graphics.Rect;
    import android.hardware.Camera;
    import android.hardware.Camera.CameraInfo;
    import android.hardware.Camera.PictureCallback;
    import android.hardware.Camera.Size;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.*;
    import android.widget.FrameLayout;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.Toast;
    
    import java.io.File;
    import java.util.List;
    
    import com.cn.camerautils.BitmapUtil;
    import com.cn.camerautils.Debug;
    import com.cn.camerautils.PathManager;
    import com.cn.qsign.R;
    
    @SuppressLint("NewApi")
    //默认的相机为横平,所以Activity设置为横屏,拍出的照片才正确
    public class ActivityCapture extends Activity implements
            View.OnClickListener, CaptureSensorsObserver.RefocuseListener {
        private ImageView bnToggleCamera;
        private ImageView bnCapture;
    
        private RelativeLayout layback;
        private FrameLayout framelayoutPreview;
        private CameraPreview preview;
        private CameraCropBorderView cropBorderView;
        private Camera camera;
        private PictureCallback pictureCallBack;
        private Camera.AutoFocusCallback focusCallback;
        private CaptureSensorsObserver observer;
        private View focuseView;
    
        private int currentCameraId;
        private int frontCameraId;
        private boolean _isCapturing;
    
        CaptureOrientationEventListener _orientationEventListener;
        private int _rotation;
    
        public static final int kPhotoMaxSaveSideLen = 1600;
        public static final String kPhotoPath = "photo_path";
    
        //    private ShutterCallback _shutterCallback = new ShutterCallback() {
        //        @Override
        //        public void onShutter() {
        //        }
        //    };
    
        final static String TAG = "capture";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            observer = new CaptureSensorsObserver(this);
            _orientationEventListener = new CaptureOrientationEventListener(this);
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_capture);
            getViews();
            initViews();
            setListeners();
            setupDevice();
            
        }
    
        @Override
        protected void onDestroy() {
            if (null != observer) {
                observer.setRefocuseListener(null);
                observer = null;
            }
            _orientationEventListener = null;
    
            super.onDestroy();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            releaseCamera(); // release the camera immediately on pause event
    
            observer.stop();
            _orientationEventListener.disable();
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            //openCamera();
            switchCamera();
        }
    
        private void releaseCamera() {
            if (camera != null) {
                camera.release(); // release the camera for other applications
                camera = null;
            }
    
            if (null != preview) {
                framelayoutPreview.removeAllViews();
                preview = null;
            }
        }
    
        protected void getViews() {
            bnToggleCamera = (ImageView) findViewById(R.id.bnToggleCamera);
            bnCapture = (ImageView) findViewById(R.id.bnCapture);
            framelayoutPreview = (FrameLayout) findViewById(R.id.cameraPreview);
            focuseView = findViewById(R.id.viewFocuse);
            layback=(RelativeLayout)findViewById(R.id.layback);
        }
    
        protected void initViews() {
            bnCapture.setRotation(-90);
            bnToggleCamera.setRotation(-90);
        }
    
        protected void setListeners() {
            bnToggleCamera.setOnClickListener(this);
            bnCapture.setOnClickListener(this);
            observer.setRefocuseListener(this);
            layback.setOnClickListener(this);
            pictureCallBack = new PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    _isCapturing = false;
                    Bitmap bitmap = null;
                    try {
                        BitmapFactory.Options options = new BitmapFactory.Options();
                        options.inJustDecodeBounds = true;
                        BitmapFactory.decodeByteArray(data, 0, data.length, options);
                        //                    Debug.debug("width--:" + options.outWidth + "  height--:" + options.outHeight);
                        options.inJustDecodeBounds = false;
                        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                        //此处就把图片压缩了
                        options.inSampleSize = Math.max(options.outWidth
                                / kPhotoMaxSaveSideLen, options.outHeight
                                / kPhotoMaxSaveSideLen);
                        bitmap = BitmapUtil.decodeByteArrayUnthrow(data, options);
                        if (null == bitmap) {
                            options.inSampleSize = Math.max(2, options.inSampleSize * 2);
                            bitmap = BitmapUtil.decodeByteArrayUnthrow(data, options);
                        }
                    } catch (Throwable e) {
                    }
                    if (null == bitmap) {
                        Toast.makeText(ActivityCapture.this, "内存不足,保存照片失败!", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    //long start = System.currentTimeMillis();
                    Bitmap addBitmap = BitmapUtil.rotateAndScale(bitmap, _rotation, kPhotoMaxSaveSideLen, true);
                    Bitmap finalBitmap = cropPhotoImage(addBitmap);
                    File photoFile = PathManager.getCropPhotoPath();
                    boolean successful = BitmapUtil.saveBitmap2file(finalBitmap, photoFile, Bitmap.CompressFormat.JPEG, 100);
                    while (!successful) {
                        successful = BitmapUtil.saveBitmap2file(finalBitmap, photoFile, Bitmap.CompressFormat.JPEG, 100);
                    }
                    if (finalBitmap != null && !finalBitmap.isRecycled()) {
                        addBitmap.recycle();
                    }
                    Intent intent = new Intent(ActivityCapture.this,ShowImageActivity.class);
                    intent.putExtra(kPhotoPath, photoFile.getAbsolutePath());
                    currentCameraId = 0;
                    ActivityCapture.this.startActivity(intent);
                    //setResult(1, intent);            
                    //ActivityCapture.this.finish();
                }
            };
            focusCallback = new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean successed, Camera camera) {
                    focuseView.setVisibility(View.INVISIBLE);
                }
            };
        }
    
        //根据拍照的图片来剪裁
        private Bitmap cropPhotoImage(Bitmap bmp) {
            int dw = bmp.getWidth();
            int dh = bmp.getHeight();
            int height;
            int width;
            if (dh > dw) {//图片竖直方向
                //切图片时按照竖屏来计算
                height = getWindowManager().getDefaultDisplay().getWidth();
                width = getWindowManager().getDefaultDisplay().getHeight();
            } else {//图片是水平方向
                //切图片时按照横屏来计算
                width = getWindowManager().getDefaultDisplay().getWidth();
                height = getWindowManager().getDefaultDisplay().getHeight();
            }
            Rect rect = new Rect();
            int left = 0;
            int top = 0;
            int right = width;
            int bottom = height;
            rect.set(left, top, right, bottom);
            float scale = 1.0f;
            // 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高
            if (dw > width && dh <= height) {
                scale = width * 1.0f / dw;
            }
            if (dh > height && dw <= width) {
                scale = height * 1.0f / dh;
            }
            // 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小
            if (dw > width && dh > height) {
                scale = Math.max(width * 1.0f / dw, height * 1.0f / dh);
            }
            //如果图片的宽度和高度都小于屏幕的宽度和高度,则放大至屏幕大小
            if (dw < width && dh < height) {
                scale = width * 1.0f / dw;
            }
            Matrix matrix = new Matrix();
            matrix.postScale(scale, scale);
            try {
                Bitmap b2 = Bitmap.createBitmap(bmp, 0, 0, dw, dh, matrix, true);
                if (null != b2 && bmp != b2) {
                    bmp.recycle();
                    bmp = b2;
                }
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
            }
            try {
                Bitmap b3 = Bitmap.createBitmap(bmp, rect.left, rect.top, rect.width(), rect.height());
                if (null != b3 && bmp != b3) {
                    bmp.recycle();
                    bmp = b3;
                }
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
            }
            //将图片压缩至640*640
            try {
                Bitmap b4 = Bitmap.createScaledBitmap(bmp, 640, 640, false);
                if (null != b4 && bmp != b4) {
                    bmp.recycle();
                    bmp = b4;
                }
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
            }
            return bmp;
        }
    
        private void setupDevice() {
            if (android.os.Build.VERSION.SDK_INT > 8) {
                int cameraCount = Camera.getNumberOfCameras();
    
                if (cameraCount < 1) {
                    Toast.makeText(this, "你的设备木有摄像头。。。", Toast.LENGTH_SHORT).show();
                    finish();
                    return;
                } else if (cameraCount == 1) {
                    bnToggleCamera.setVisibility(View.INVISIBLE);
                } else {
                    bnToggleCamera.setVisibility(View.VISIBLE);
                }
    
                currentCameraId = 0;
                frontCameraId = findFrontFacingCamera();
                if (-1 == frontCameraId) {
                    bnToggleCamera.setVisibility(View.INVISIBLE);
                }
            }
        }
    
        private void openCamera() {
            if (android.os.Build.VERSION.SDK_INT > 8) {
                try {
                    camera = Camera.open(currentCameraId);
                } catch (Exception e) {
                    Toast.makeText(this, "摄像头打开失败", Toast.LENGTH_SHORT).show();
                    finish();
                    return;
                }
                setCameraDisplayOrientation(this, 0, camera);
            } else {
                try {
                    camera = Camera.open();
                } catch (Exception e) {
                    Toast.makeText(this, "摄像头打开失败", Toast.LENGTH_SHORT).show();
                    finish();
                    return;
                }
            }
    
            Camera.Parameters camParmeters = camera.getParameters();
            List<Size> sizes = camParmeters.getSupportedPreviewSizes();
            for (Size size : sizes) {
                Log.v(TAG, "w:" + size.width + ",h:" + size.height);
            }
    
            preview = new CameraPreview(this, camera);
            cropBorderView = new CameraCropBorderView(this);
            FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
            framelayoutPreview.addView(preview, params1);
            //framelayoutPreview.addView(cropBorderView, params1);
            observer.start();
            _orientationEventListener.enable();
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.bnToggleCamera:
                switchCamera();
                break;
            case R.id.bnCapture:
                bnCaptureClicked();
                break;
            case R.id.layback:
                finish();
                break;
            }
        }
    
        @Override
        public void onBackPressed() {
            super.onBackPressed();
        }
    
        //横竖屏切换的时候
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
        }
    
        private void switchCamera() {
            if (currentCameraId == 0) {
                currentCameraId = frontCameraId;
            } else {
                currentCameraId = 0;
            }
            releaseCamera();
            openCamera();
        }
    
        private void bnCaptureClicked() {
            if (_isCapturing) {
                return;
            }
            _isCapturing = true;
            focuseView.setVisibility(View.INVISIBLE);
    
            try {
                camera.takePicture(null, null, pictureCallBack);
            } catch (RuntimeException e) {
                e.printStackTrace();
                _isCapturing = false;
            }
        }
    
        /**
         * A basic Camera preview class
         */
        public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
            private SurfaceHolder mHolder;
            private Camera mCamera;
    
            @SuppressWarnings("deprecation")
            public CameraPreview(Context context, Camera camera) {
                super(context);
                mCamera = camera;
    
                // Install a SurfaceHolder.Callback so we get notified when the
                // underlying surface is created and destroyed.
                mHolder = getHolder();
                mHolder.addCallback(this);
                // deprecated setting, but required on Android versions prior to 3.0
                mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            }
    
            public void surfaceCreated(SurfaceHolder holder) {
                // The Surface has been created, now tell the camera where to draw
                // the preview.
                try {
                    mCamera.setPreviewDisplay(holder);
                    mCamera.startPreview();
                } catch (Exception e) {
                    Log.d(TAG, "Error setting camera preview: " + e.getMessage());
                }
            }
    
            public void surfaceDestroyed(SurfaceHolder holder) {
                // empty. Take care of releasing the Camera preview in your
                // activity.
                if (camera != null) {
                    camera.setPreviewCallback(null);
                    camera.stopPreview();// 停止预览
                    camera.release(); // 释放摄像头资源
                    camera = null;
                }
            }
    
            private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
                final double ASPECT_TOLERANCE = 0.05;
                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;
            }
    
            private Size getOptimalPictureSize(List<Size> sizes, double targetRatio) {
                final double ASPECT_TOLERANCE = 0.05;
    
                if (sizes == null)
                    return null;
    
                Size optimalSize = null;
                int optimalSideLen = 0;
                double optimalDiffRatio = Double.MAX_VALUE;
    
                for (Size size : sizes) {
    
                    int sideLen = Math.max(size.width, size.height);
                    //LogEx.i("size. " + size.width + ", size.height: " + size.height);
                    boolean select = false;
                    if (sideLen < kPhotoMaxSaveSideLen) {
                        if (0 == optimalSideLen || sideLen > optimalSideLen) {
                            select = true;
                        }
                    } else {
                        if (kPhotoMaxSaveSideLen > optimalSideLen) {
                            select = true;
                        } else {
                            double diffRatio = Math.abs((double) size.width / size.height - targetRatio);
                            if (diffRatio + ASPECT_TOLERANCE < optimalDiffRatio) {
                                select = true;
                            } else if (diffRatio < optimalDiffRatio + ASPECT_TOLERANCE && sideLen < optimalSideLen) {
                                select = true;
                            }
                        }
                    }
    
                    if (select) {
                        optimalSize = size;
                        optimalSideLen = sideLen;
                        optimalDiffRatio = Math.abs((double) size.width / size.height - targetRatio);
                    }
                }
    
                return optimalSize;
            }
    
            public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
                // If your preview can change or rotate, take care of those events
                // here.
                // Make sure to stop the preview before resizing or reformatting it.
    
                Debug.debug("surfaceChanged format:" + format + ", w:" + w + ", h:" + h);
                if (mHolder.getSurface() == null) {
                    // preview surface does not exist
                    return;
                }
    
                // stop preview before making changes
                try {
                    mCamera.stopPreview();
                } catch (Exception e) {
                    // ignore: tried to stop a non-existent preview
                }
    
                try {
                    Camera.Parameters parameters = mCamera.getParameters();
    
                    List<Size> sizes = parameters.getSupportedPreviewSizes();
                    Size optimalSize = getOptimalPreviewSize(sizes, w, h);
                    parameters.setPreviewSize(optimalSize.width, optimalSize.height);
                    double targetRatio = (double) w / h;
                    sizes = parameters.getSupportedPictureSizes();
                    optimalSize = getOptimalPictureSize(sizes, targetRatio);
                    parameters.setPictureSize(optimalSize.width, optimalSize.height);
                    parameters.setRotation(0);
                    mCamera.setParameters(parameters);
                } catch (Exception e) {
                    Debug.debug(e.toString());
                }
    
                // set preview size and make any resize, rotate or
                // reformatting changes here
    
                // start preview with new settings
                try {
                    mCamera.setPreviewDisplay(mHolder);
                    mCamera.startPreview();
                } catch (Exception e) {
                    Debug.debug("Error starting camera preview: " + e.getMessage());
                }
            }
        }
    
        private int findFrontFacingCamera() {
            int cameraId = -1;
            // Search for the front facing camera
            int numberOfCameras = Camera.getNumberOfCameras();
            for (int i = 0; i < numberOfCameras; i++) {
                CameraInfo info = new CameraInfo();
                Camera.getCameraInfo(i, info);
                if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                    Log.d(TAG, "Camera found");
                    cameraId = i;
                    break;
                }
            }
            return cameraId;
        }
    
        private static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(cameraId, info);
            int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
            int degrees = 0;
            switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
            }
    
            int result;
            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                result = (info.orientation + degrees) % 360;
                result = (360 - result) % 360; // compensate the mirror
            } else { // back-facing
                result = (info.orientation - degrees + 360) % 360;
            }
    
            //LogEx.i("result: " + result);
            camera.setDisplayOrientation(result);
        }
    
        @Override
        public void needFocuse() {
    
            //LogEx.i("_isCapturing: " + _isCapturing);
            if (null == camera || _isCapturing) {
                return;
            }
    
            //LogEx.i("autoFocus");
            camera.cancelAutoFocus();
            try {
                camera.autoFocus(focusCallback);
            } catch (Exception e) {
                Debug.debug(e.toString());
                return;
            }
    
            if (View.INVISIBLE == focuseView.getVisibility()) {
                focuseView.setVisibility(View.VISIBLE);
                focuseView.getParent().requestTransparentRegion(preview);
            }
        }
    
        //相机旋转监听的类,最后保存图片时用到
        private class CaptureOrientationEventListener extends OrientationEventListener {
            public CaptureOrientationEventListener(Context context) {
                super(context);
            }
    
            @Override
            public void onOrientationChanged(int orientation) {
                if (null == camera)
                    return;
                if (orientation == ORIENTATION_UNKNOWN)
                    return;
    
                orientation = (orientation + 45) / 90 * 90;
                if (android.os.Build.VERSION.SDK_INT <= 8) {
                    _rotation = (90 + orientation) % 360;
                    return;
                }
    
                CameraInfo info = new CameraInfo();
                Camera.getCameraInfo(currentCameraId, info);
    
                if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                    _rotation = (info.orientation - orientation + 360) % 360;
                } else { // back-facing camera
                    _rotation = (info.orientation + orientation) % 360;
                }
            }
        }
    }
  • 相关阅读:
    python自动化_day3_基础数据类型的整理
    python自动化_day2_基础数据类型0410
    解决PowerDesigner 12 建Oracle 9i数据库脚本双引号问题(转抄)
    获取WPF资源,生成文件
    DataTable 用法归纳
    VS2008开发环境中容易遇到的3个问题之解决办法(转载)
    调用线程必须为 STA,因为许多 UI 组件都需要(转载)
    无法在Web服务器上启动调试。您不具备调试此应用程序的权限_解决方法
    js 数组去重问题
    HTML空格转义字符的使用
  • 原文地址:https://www.cnblogs.com/exmyth/p/8534646.html
Copyright © 2011-2022 走看看