使用ACTION_IMAGE_CAPTURE拍摄的图像在某些Gingerbread设备上的ExifInterface.TAG_ORIENTATION返回1

Tol*_*a E 40 android exif image-capture orientation

在处理ACTION_IMAGE_CAPTURE活动时我遇到了方向问题.我已经使用过,TAG_ORIENTATION所以我会相应地旋转图片.但现在我们发现在一些较新的设备上这不起作用.事实上,它为所有方向返回1.

这是我们观察到的设备列表;

  • 三星Infuse 4G(2.3.3)
  • 三星Galaxy SII X(2.3.5)
  • 索尼Xperia Arc(2.3.3)

有趣的是,一旦这个图像是图库它正确显示,如果我选择它,TAG_ORIENTATION就会正确填充.所以不知何故OS正确地填写了这些信息,但没有ActivityResult.

确定方向的最可靠方法是什么?有人在另一个问题上建议比较高度和宽度但是在获得这些时,它们会根据方向正确切换(另一个谜)

编辑:似乎这可能连接到另一个错误,其中操作系统复制在库中拍摄的图像(它只应该将图像保存在我们指定的URL中),事情是这个图像在库中有ORIENTATION信息而指定位置的一个没有.

这是错误; http://code.google.com/p/android/issues/detail?id=19268

编辑2:我已经向Android提交了一个新的错误.我很确定这是与上述错误相关的操作系统错误. http://code.google.com/p/android/issues/detail?id=22822

Tol*_*a E 53

好吧,看起来这个Android的bug将暂时无法修复.虽然我找到了一种方法来实现ExifInformation,以便两个设备(具有正确的Exif标签,以及不正确的exif标签一起工作).

所以问题出现在一些(较新的)设备上,有一个错误,使得拍摄的照片保存在您的app文件夹中没有正确的exif标签,而正确旋转的图像保存在android默认文件夹中(即使它不应该). .

现在我做的是,我记录我从我的应用程序启动相机应用程序的时间.在活动结果上,我查询媒体提供商,看看在我保存的这个时间戳之后是否保存了任何图片.这意味着,最有可能的操作系统在默认文件夹中保存的正确旋转图片,当然摆在媒体存储一个条目,我们就可以使用来自该行的旋转信息.现在,以确保我们正在寻找合适的形象,我比较这文件到一个我访问的大小(保存在自己的应用程序文件夹);

    int rotation =-1;
    long fileSize = new File(filePath).length();

    Cursor mediaCursor = content.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] {MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.MediaColumns.SIZE }, MediaStore.MediaColumns.DATE_ADDED + ">=?", new String[]{String.valueOf(captureTime/1000 - 1)}, MediaStore.MediaColumns.DATE_ADDED + " desc");

    if (mediaCursor != null && captureTime != 0 && mediaCursor.getCount() !=0 ) {
        while(mediaCursor.moveToNext()){
            long size = mediaCursor.getLong(1);
            //Extra check to make sure that we are getting the orientation from the proper file
            if(size == fileSize){
                rotation = mediaCursor.getInt(0);
                break;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在,如果此时的旋转仍为-1,则表示这是具有正确旋转信息的手机之一.此时,我们可以在返回到onActivityResult的文件上使用常规exif方向

    else if(rotation == -1){
        rotation = getExifOrientationAttribute(filePath);
    }
Run Code Online (Sandbox Code Playgroud)

您可以轻松找到如何找到exif方向,如Android中的相机方向问题中的答案

另请注意,只有在Api等级5之后才支持ExifInterface.因此,如果您想在2.0之前支持手机,那么您可以使用我找到的这个方便的库,用于Java提供的Drew Noakes; http://www.drewnoakes.com/code/exif/

祝你的形象旋转好运!

编辑:因为有人问,我使用的意图和我的开始是这样的

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//mediaFile is where the image will be saved
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaFile));
startActivityForResult(intent, 1);
Run Code Online (Sandbox Code Playgroud)

  • @TolgaE"captureTime"是System.currenttimeinMillis()对吗? (3认同)

ofe*_*iko 7

你也可以这样走:

Matrix matrix = new Matrix();
// rotate the Bitmap (there a problem with exif so we'll query the mediaStore for orientation
Cursor cursor = getApplicationContext().getContentResolver().query(selectedImage,
      new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
if (cursor.getCount() == 1) {
cursor.moveToFirst();
    int orientation =  cursor.getInt(0);
    matrix.preRotate(orientation);
    }
Run Code Online (Sandbox Code Playgroud)


l33*_*33t 7

确实是一个有问题的错误!我不确定我喜欢建议的解决方法,所以这里是另一个:)

关键是EXTRA_OUTPUT在捕获图像时使用和查询它!显然,这只有在您允许自己指定文件名时才有效.

protected void takePictureSequence() {      
    try {
        ContentValues values = new ContentValues();  
        values.put(MediaStore.Images.Media.TITLE, UUID.randomUUID().toString() + ".jpg");  
        newPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, newPhotoUri);

        startActivityForResult(intent, ActivityResults.TAKE_NEW_PICTURE_RESULT);
    } catch (Exception e) {
        Toast.makeText(this, R.string.could_not_initalize_camera, Toast.LENGTH_LONG).show();
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == ActivityResults.TAKE_NEW_PICTURE_RESULT) {
        if (resultCode == RESULT_OK) {
            try {
                String[] projection = { MediaStore.Images.Media.DATA }; 
                CursorLoader loader = new CursorLoader(this, newPhotoUri, projection, null, null, null);
                Cursor cursor = loader.loadInBackground();

                int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();

                // Rotation is stored in an EXIF tag, and this tag seems to return 0 for URIs.
                // Hence, we retrieve it using an absolute path instead!
                int rotation = 0;
                String realPath = cursor.getString(column_index_data);
                if (realPath != null) {
                    rotation = ImageHelper.getRotationForImage(realPath);
                }

                // Now we can load the bitmap from the Uri, using the correct rotation.
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public int getRotationForImage(String path) {
    int rotation = 0;

    try {
        ExifInterface exif = new ExifInterface(path);
        rotation = (int)exifOrientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return rotation;
}
Run Code Online (Sandbox Code Playgroud)