某些图片尺寸导致Camera.takePicture()失败

时间:2015-05-14 13:58:06

标签: android android-camera

摘要:对于某些图片尺寸,在调用Camera.takePicture()后,将相机图片大小明确设置为支持的大小会导致无法调用回调。

详细信息:

我正在开发一款使用Camera API捕捉图像的简单相机应用。它遵循Camera类文档中描述的准则,并在各种设备上可靠地运行。

在调用Camera.open()之后,应用程序调用camera.getParameters()来获取Camera.Parameters对象,然后调用此对象的getSupportedPictureSizes()。它迭代支持的图片大小,并选择一个符合某些标准的大小对。然后调用setPictureSize(),传入选定的宽度和高度。最后,它通过调用camera.SetParameters()来设置摄像机参数,传入Camera.Parameters对象。

我遇到了HTC Desire 620的问题。此设备上报告的支持图片尺寸之一是1184x1184。如果我设置此图片大小然后调用camera.takePicture(),则不会调用任何回调(快门,原始或jpeg),并且相机对象似乎处于无效状态。如果我明确地将图片大小设置为任何其他支持的大小(方形或矩形宽高比),则调用回调。但对于1184x1184,他们不是。

有人遇到过这样的事吗?有没有办法事先知道支持的图片大小是否会导致这类问题?我在这里缺少什么?

编辑:拼写错误

2 个答案:

答案 0 :(得分:1)

我没有 HTC Desire 620 ,因此我无法验证您的发现。但我在Android相机开发中看到了不少设备。您描述的问题是确实发生的情况之一。我宁愿忘记Honeycomb 2.3的日子,其中每个支持的设备都需要自己的一套变通方法。但即使以后事情也永远不会完美。

例如,Galaxy Nexus设备声称支持QVGA和getSupportedPreviewSizes()。但事实并非如此。将预览大小设置为320x240仍会在onPreviewFrame()中生成640x480字节数组。

许多错误与视频与预览尺寸有关。纵向方向会弹出一些错误。等等。

正如您经常注意到的那样,有问题的设置只会导致回调永远不会到来。但是总是用try ... catch包装camera.setParameters()和其他相机调用仍然是一个好习惯。

密切关注奇怪的依赖关系:例如夜景不能与连续焦点共存。不幸的是,我们所知道的Camera API无法提供此类信息。

如果您浏览处理各种相机设备的开源项目,您会发现它们会跟踪不成功的设置(参数集),并且只会失败一次。

更新我遇到的一个非显而易见的依赖项是设置预览大小和设置图片大小。例如。当后者的宽高比为16:9时,图片无法设置为4:3。

更新 here 是一个错误的支持'三星Galaxy S3的图片尺寸。使用它会导致相机错误1001。

答案 1 :(得分:0)

这是我的代码,用于拍照,并将其保存在数据库中,而不会改变其质量。也许它不是你想要的,但它可以帮助你。

首先你需要这个变量:

 private static final int CAMERA_PIC_REQUEST = 2500;
private Rect Padding = new Rect(-1,-1,-1,-1);
private Matrix matrix = new Matrix();
private Bitmap rotatedBitmap = null;
private Bitmap bm = null;
private Bitmap scaledBitmap= null;
private ExifInterface exif ;
private int rotation=0;
private final BitmapFactory.Options options = new BitmapFactory.Options();

然后根据您的应用(我使用按钮)从按钮,活动或片段设置请求

btn_camera.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {

              Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
              startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);

          }
    }
    );

现在我正在请求CAMERA 来自片段的_PIC_REQUEST我在OnActivityResult()

上实现了这个代码
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAMERA_PIC_REQUEST)
        if (data != null) {
        imageuri = data.getData();
        //Bitmap image = (Bitmap) data.getExtras().get("data");

        try {
            options.inSampleSize = 2;
            exif = new ExifInterface(getRealPathFromURI(imageuri));
            rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            rotation = exifToDegrees(rotation);

            bm = BitmapFactory.decodeStream(
                    getActivity().getContentResolver().openInputStream(imageuri),Padding,options);

            scaledBitmap = Bitmap.createScaledBitmap(bm, 400,400, true);

            if (rotation != 0)
            {matrix.postRotate(rotation);}
            //matrix.postRotate(180);
            rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        mIvFoto.setImageBitmap(rotatedBitmap);


     }
 }

旋转和矩阵用于将拍摄的照片缩放到ImageView,因此我可以在保存之前预览照片。这不会影响pic的质量。它只适用于预览位图。所以在ScaledBitmap变量中,你可以看到,当我将PIC的尺寸放到400,400时,你可以放置你想要的图片的尺寸,一定要旋转位图,这样你就可以正确地拍照了即使您以纵向模式拍摄照片。

最后是从相机保存它的路径旋转和获取图片的方法。

private static int exifToDegrees(int exifOrientation) {
    if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {  return 180; }
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {  return 270; }
    return 0;
}

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor =getActivity().getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { // Source is Dropbox or other similar local file path
        result = contentURI.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

我希望这对你有所帮助。