Android 某些图片大小导致Camera.takePicture()失败

Android 某些图片大小导致Camera.takePicture()失败,android,android-camera,Android,Android Camera,摘要:显式地将相机图片大小设置为支持的大小会导致在相机之后不调用回调。对于某些图片大小,会调用takePicture() 详细信息: 我正在开发一个简单的摄像头应用程序,它使用摄像头API捕捉图像。它遵循Camera类文档中描述的指导原则,可在各种设备上可靠工作 调用Camera.open()后,应用程序调用Camera.getParameters()以获取Camera.Parameters对象,然后调用此对象的getSupportedPictureSizes()。它迭代支持的图片大小,并选择一

摘要:显式地将相机图片大小设置为支持的大小会导致在相机之后不调用回调。对于某些图片大小,会调用takePicture()

详细信息:

我正在开发一个简单的摄像头应用程序,它使用摄像头API捕捉图像。它遵循Camera类文档中描述的指导原则,可在各种设备上可靠工作

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

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


有人遇到过这样的事情吗?有没有办法提前知道支持的图片大小是否会导致此类问题?我错过了什么


编辑:打字

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

首先,您需要以下变量:

 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();
然后根据您的应用程序,从按钮、活动或片段设置请求(我的应用程序使用按钮)

现在,我要的是相机 _来自片段的picu请求我在OnActivityResult()上实现了这段代码

旋转和矩阵用于将拍摄的照片缩放到ImageView,这样我可以在保存前预览照片。这不会影响照片的质量。这只是预览位图。因此,在ScaledBitmap变量中,如您所见,在创建ScaledBitmap时,我放置图片的尺寸,到400400,您可以放置您想要获得的图片的尺寸,确保旋转位图,这样您就可以获得正确的图片,即使您以纵向模式拍照

最后介绍了从相机保存的路径旋转和获取图片的方法

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;
}
我希望这能对您有所帮助。

我没有HTC Desire 620,因此无法验证您的发现。但在我从事Android摄像头开发的过程中,我看到了不少设备。您所描述的问题是确实发生的情况之一。我更愿意忘记蜂巢2.3的时代,每个受支持的设备都需要自己的解决方案。但即使是后来,事情也从未完美过

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

很多错误都与视频和预览大小有关。在纵向方向上会出现一些bug。等等

正如您所注意到的,有问题的设置通常只会导致回调无法到达。但始终使用try…catch包装
camera.setParameters()
和其他camera调用仍然是一个很好的做法

注意奇怪的相关性:例如,夜景不能与连续聚焦共存。不幸的是,我们所知的摄像头API无法提供此类信息

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

更新我遇到的一个不明显的依赖关系是设置预览大小和设置图片大小。例如,当后者的纵横比为16:9时,图片无法设置为4:3


更新并且是关于三星Galaxy S3中错误的“支持”图片大小的故事。使用它会导致相机错误1001。

因此,该代码在其他尺寸的相机上运行良好?“有人遇到过任何链接吗?”--如果是“链接”,你的意思是“像”,是的,我遇到过不少。“有没有办法提前知道支持的图片大小是否会导致此类问题?”——据我所知,没有提前知道。“我在这里遗漏了什么?”——安卓设备制造商,特别是负责摄像头API的制造商的稳健质量控制理念。@Braim是的,它适用于除1184x1184之外的所有34种支持图片大小。我之所以感兴趣,是因为我也在编写摄像头应用程序。我用于测试的LG G3没有遇到类似问题。@Braim我已经在各种设备(包括其他HTC)上测试过它,这是我第一次遇到这个问题。正如我所说,该应用程序在各种设备上都运行良好。问题在于设置一个显式的图片大小,而您的代码似乎没有这样做。但是谢谢你的回应,看看别人是怎么做的总是很有用的。谢谢你的回应。我正在考虑使用计时器捕捉回调从未到达的情况,并将图片大小添加到“忽略列表”中。我更愿意以用户看不见的方式处理问题,但是,由于摄影机对象处于无效状态,我需要将其与曲面支架分离,这会导致可见的小故障。您是否有任何指向以干净方式处理此类问题的代码的指针?当您为1184x118调用
takePicture()
时,预览曲面是否冻结?然后,您可以简单地更改相机参数而不中断
@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);


     }
 }
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;
}