美文网首页
android 自定义相机 遇到的问题

android 自定义相机 遇到的问题

作者: 古早味蛋糕 | 来源:发表于2019-03-12 15:43 被阅读0次

    1.预览图相拉伸
    2.预览黑屏
    3.PictureCallback无响应
    4.finish当前页面报错

    首先 预览图相拉伸 是由于 SurfaceView 的尺寸 与 PreviewSize(预览尺寸) 比例不相同导致的。

    解决办法 设置 预览尺寸

     //设置预览尺寸  
     Camera.Parameters parameters = c.getParameters();  
     parameters.setPreviewSize(size.width, size.height);   
     //设置SurfaceView尺寸  
     Size size = mCamera.getParameters().getPreviewSize();
     float scale = this.getWidth()/Float.parseFloat(size.height+"");  
     this.getLayoutParams().height = (int) (size.width*scale);
    

    这样能解决 预览拉伸的问题

    当然 这里 涉及到 怎么样取 合适的 预览尺寸 ,以下的网上的一个参考

         /**
         * 获取最适合屏幕的照片 尺寸
         *
         * @param sizes
         * @param w
         * @param h
         * @return
         */
        public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            double targetRatio = (double) w / h;
            if (sizes == null)
                return null;
    
            Camera.Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;
    
            int targetHeight = h;
    
            // Try to find an size match aspect ratio and size
            for (Camera.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 (Camera.Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                    }
                }
            }
            return optimalSize;
        }
    

    具体获取“最适合的尺寸”

        //先取到所有的预览尺寸,再按屏幕的宽高来获取“最适合”的尺寸  
        //当然如果你的SurfaceView 不是按屏幕宽高来的 你需要以SurfaceView宽高为准  
        //注意 因为 预览的时候 需要 旋转90度。所以这里的宽是高  高 即是宽  
        List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
        Size size = getOptimalPreviewSize(sizes, dm.heightPixels, dm.widthPixels);
    

    黑屏以及PictureCallback无响应 都有可能是 设置了不合适的相片尺寸 (setPictureSize)

    如果想预览的内容即等于生成的相片的内容,可能需要 将 预览尺寸与相片尺寸设置相同,或者比例相同

    但事不与人愿,一般来说将相片尺寸设置成 相片尺寸 不会有太大的问题,但在某些情况下是不行的。因为预览尺寸里有的尺寸 有可能 在相片尺寸中不存在,这个时候会出现 预览黑屏 或者 相机回调无响应

    博主解决办法为:先获取“最适合” 屏幕的 相片尺寸,再按相片尺寸来取最“合适”的预览尺寸,根据预览的尺寸再来调整SurfaceView的尺寸

        Camera c = Camera.open();
        Camera.Parameters parameters = c.getParameters();
        //先找最合适的照片尺寸
        List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
        Size pictureSize = getOptimalPreviewSize(pictureSizes, dm.heightPixels, dm.widthPixels);
        parameters.setPictureSize(pictureSize.width,pictureSize.height);
    
        //再找最合适的预览尺寸
        List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
        Size size = getOptimalPreviewSize(sizes, pictureSize.width, pictureSize.height);
        parameters.setPreviewSize(size.width,size.height);
        c.setParameters(parameters);
    
        //再调整SurfaceView 宽高,注意 调整宽高得在SurfaceView能获取宽高的时候
        //博主是在surfaceCreated方法中调整的
        Size size = mCamera.getParameters().getPreviewSize();
        float scale = this.getWidth() / Float.parseFloat(size.height + "");
        this.getLayoutParams().height =(int)(size.width*scale);
    

    既然 预览的尺寸比较与相片的尺寸比例相同,那取SurfaceView中的部分内容当然是很容易了。

    首先肯定在SurfaceView层上画了一个矩形 或者 别的啥形,按图片的实际尺寸 等比缩放,然后用bitmap裁 剪即可

    关键代码

        PictureCallback callback = new PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                releaseCamera();
    
    
                //旋转90度  
                Bitmap bMap = BitmapFactory.decodeByteArray(data, 0, data.length);
                Bitmap bMapRotate;
                Matrix matrix = new Matrix();
                matrix.reset();
                matrix.postRotate(90);
                bMapRotate = Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(), bMap.getHeight(), matrix, false);
    
                //截取矩形内照片  
                ViewfinderView vf = (ViewfinderView) findViewById(R.id.viewfinder_view);
                float scale = bMapRotate.getWidth() / Float.valueOf(vf.getWidth());
                int width = (int) (vf.rwidth * scale);
                int height = (int) (vf.rheight * scale);
                bMapRotate = Bitmap.createBitmap(bMapRotate, (int) (vf.leftOffset * scale), (int) (vf.topOffset * scale), width, height);
                bMap = bMapRotate;
    
                //Intent intent = new Intent();  
                //intent.putExtra("data", data);  
                //设置返回数据  
                //CameraActivity.this.setResult(RESULT_OK);  
                CameraActivity.this.finish(); 
             }
        };
    

    这里可能会出现finish无响应的问题,如果 将 裁剪完的bitmap 直接放入 intent中,虽然没看到报啥错,但是finish当然页面 无反应,clone 一个bitmap再传 问题依旧,博主将bitmap转成byte[] 解决了问题,但是图片过大的时候又会出现新的问题,事务过大。没法传。当然你也可能先存成文件,再传一个文件路径过去,但是如果回跳的页面中用到了bitmap 这个时候又得将file decodefile成bitmap 感觉无用功很多。 实现没办法只能推荐用静态变量的方法。博主解决为在Application中添加几个静态方法

        private static Object object;
    
        public static void set(Object obj){
            Application.object = obj;
        }
    
        public static Object get(){
            return Application.object;
        }
    
        @SuppressWarnings("unchecked")
        public static <T> T get(Class<T> clazz){
            return (T)Application.object;
        }
    
        public static void clear(){
            Application.object = null;
        }
    

    具体使用为:

        //先塞值  
        Application.set(bMap);
    
        //回调页面中再取值  
        Bitmap bMap = Application.get(Bitmap.class);

    相关文章

      网友评论

          本文标题:android 自定义相机 遇到的问题

          本文链接:https://www.haomeiwen.com/subject/xrknpqtx.html