找茬小王子 2023-09-25 10:52 采纳率: 50%
浏览 7
已结题

安卓camera保存的图片打开显示全黑色

我平板上的camera保存的图片在电脑上可以正常显示,在平板上打开却是一张全黑色的图片,这是什么原因?
代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener,Camera.PreviewCallback {
    private SurfaceView surfaceView;
    private Button photograph;
    private Button recording;
    private Button switchs;

    private int rotation;
    private int shortSize;
    private int longSize;
    private Camera camera;
    private Camera.CameraInfo cameraInfo;
    private Camera.Parameters parameters;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        surfaceView = (SurfaceView) findViewById(R.id.camera_view);
        photograph = (Button) findViewById(R.id.photograph);
        recording = (Button) findViewById(R.id.recording);
        switchs = (Button) findViewById(R.id.switchs);

        photograph.setOnClickListener(this);
        recording.setOnClickListener(this);
        switchs.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.photograph:
                if (camera == null) {
                    Toast.makeText(this, "请打开相机", Toast.LENGTH_SHORT).show();
                    return;
                }
                camera.takePicture(null,null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        new SavePicAsyncTask(MainActivity.this, cameraInfo.facing, data).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

                }
                });

                break;
            case R.id.recording:

                break;
            case R.id.switchs:

                break;
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        if (hasFocus) {
            int[] a = new int[2];
            surfaceView.getLocationOnScreen(a);
            shortSize = surfaceView.getHeight();     //横屏为宽度,竖屏为高度
            longSize = surfaceView.getWidth();
            rotation = getWindowManager().getDefaultDisplay().getRotation();
            cameraInfo = new Camera.CameraInfo();
            checkCameraPermission();
        }
    }

    /*
    1.申请相机权限----------------------------------------------------------------------------------------------------------------------------
     */
    private void checkCameraPermission() {
        //检查是否有相机权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            //没权限,请求权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
                    1);
        } else {
            //有权限
            Log.d("MainActivity","有权限");
            getCameras(0);  //0为后摄,1为前摄
        }
    }

    //权限请求回调
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults != null && grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //用户同意权限
                    getCameras(0);  //0为后摄,1为前摄
                } else {
                    // 权限被用户拒绝了,可以提示用户,关闭界面等等。
                    Toast.makeText(this, "拒绝权限,请去设置里面手动开启权限", Toast.LENGTH_SHORT).show();
                }
                break;
        }

    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        camera.addCallbackBuffer(data);
    }

    public void getCameras(int lens_facing) {
        String[] cameras = new String[0];
        String cameid = "0";
        //先释放相机资源
        releaseCamera();
        //获取相机信息
        if (cameraInfo == null) {
            cameraInfo = new Camera.CameraInfo();
        }
        //获取相机个数
        int cameraCount = Camera.getNumberOfCameras();
        //由于不知道第几个是前置摄像头,遍历获取前置摄像头
        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo);

            if (cameraInfo.facing == lens_facing) {
                //根据id打开相机
                Log.d("MainActivity","相机id为"+camIdx);
                camera = Camera.open(camIdx);
                setPreview();
                break;
            }
        }

    }

    public void setPreview() {
        try {
            //设置摄像头参数
            parameters = camera.getParameters();
            //设置预览大小
            parameters.setPreviewSize(getBestSize().width, getBestSize().height);
            //设置图片大小,拍照
            parameters.setPictureSize(getBestSize().width, getBestSize().height);
            //设置格式,所有的相机都支持 NV21格式
            parameters.setPreviewFormat(ImageFormat.NV21);
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

            //修改相机摄像头参数
            camera.setParameters(parameters);
            //修改相机预览方向
            camera.setDisplayOrientation(adjustCameraOrientation());
            //绑定预览视图
            camera.setPreviewDisplay(surfaceView.getHolder());
            //设置预览数据监听
            camera.setPreviewCallbackWithBuffer(this);
            //开始预览
            camera.startPreview();
        } catch (IOException e) {

        }
    }

    /**
     * 获取预览最佳尺寸
     */
    private Camera.Size getBestSize() {
        List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
        Camera.Size bestSize = null;
        float uiRatio = (float) longSize / shortSize;
        float minRatio = uiRatio;
        for (Camera.Size previewSize : sizes) {
            float cameraRatio = (float) previewSize.width / previewSize.height;

            //如果找不到比例相同的,找一个最近的,防止预览变形
            float offset = Math.abs(cameraRatio - minRatio);
            if (offset < minRatio) {
                minRatio = offset;
                bestSize = previewSize;
            }
            //比例相同
            if (uiRatio == cameraRatio) {
                bestSize = previewSize;
                break;
            }
        }
        return bestSize;
    }

    private int adjustCameraOrientation() {
        //判断当前的横竖屏

        int degress = 0;
        //获取手机的方向
        switch (rotation) {
            case Surface.ROTATION_0:
                degress = 0;
                break;
            case Surface.ROTATION_90:
                degress = 90;
                break;
            case Surface.ROTATION_180:
                degress = 180;
                break;
            case Surface.ROTATION_270:
                degress = 270;
                break;
        }
        int result = 0;
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            result = (cameraInfo.orientation - degress + 360) % 360;
        } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (cameraInfo.orientation + degress) % 360;
            result = (360 - result) % 360;
        }
        return result;

    }

    private void releaseCamera() {
        if (camera != null) {
            camera.stopPreview();
            camera.stopFaceDetection();
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
        }
    }

    class SavePicAsyncTask extends AsyncTask<Void, Void, File> {
        Context context;
        int facing;
        byte[] data;

        public SavePicAsyncTask(Context context, int facing, byte[] data) {
            this.context = context;
            this.facing = facing;
            this.data = data;
        }
        @Override
        protected File doInBackground(Void... voids) {
            //保存的文件
            File picFile = null;
            try {
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                if (bitmap == null) {
                    return null;
                }
                //保存之前先调整方向
                if (facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    Matrix matrix = new Matrix();
                    matrix.postRotate(90);
                    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                } else {
                    Matrix matrix = new Matrix();
                    matrix.postRotate(270);
                    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                }

                // SD卡根目录
                File dir = context.getExternalFilesDir("print");
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                picFile = new File(dir, System.currentTimeMillis() + ".JPEG");
                FileOutputStream fos = new FileOutputStream(picFile);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.close();
                bitmap.recycle();
                return picFile;

            } catch (Exception e) {
                e.printStackTrace();
            }
            return picFile;
        }

        @Override
        protected void onPostExecute(File file) {
            super.onPostExecute(file);
            if (file != null) {
                Toast.makeText(context, "图片保存成功", Toast.LENGTH_SHORT).show();
                camera.startPreview();
            } else {
                Toast.makeText(context, "图片保存失败", Toast.LENGTH_SHORT).show();
            }
        }
    }
}


  • 写回答

2条回答 默认 最新

  • 不会写代码的猴子 Android领域优质创作者 2023-09-25 11:18
    关注

    既然用到了camera2,建议你把预览组件从SurfaceView 换成TextureView,有更好用的方法保存图片

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 12月5日
  • 创建了问题 9月25日

悬赏问题

  • ¥15 速帮,学校需要在外上班没空
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改
  • ¥15 Windows 系统cmd后提示“加载用户设置时遇到错误”
  • ¥50 vue router 动态路由问题
  • ¥15 关于#.net#的问题:End Function
  • ¥15 无法import pycausal
  • ¥15 VS2022创建MVC framework提示:预安装的程序包具有对缺少的注册表值的引用
  • ¥15 weditor无法连接模拟器Local server not started, start with?
  • ¥20 6-3 String类定义