某些设备(不是EXIF)捕获Android相机无法解释的旋转

Sco*_*itt 29 camera android rotation capture orientation

我正在做的事情似乎应该很简单,但在我阅读了每一个可能的Stackoverflow答案之后我仍然迷失了,我可以找到并搜索我能找到的每篇文章.

我正在使用预览SurfaceView并从我在AndroidManifest.xml中为screenOrientation ="landscape"设置的活动中捕获图像.

我按照示例相机应用程序代码进行操作,直到我在运行1.5的一些摩托罗拉设备上尝试我的应用程序之前一直工作.

我让OrientationEventListener运行正常,我使用反射来查看是否设置旋转:

final int latchedOrientation = roundOrientation(mLastOrientation + 90);

Parameters parameters = preview.camera.getParameters();

JPLog.d("Setting camera rotation = %d", latchedOrientation);
try {
    // if >= 2.0
    Method method = Camera.Parameters.class.getMethod("setRotation",
        int.class);

    if(method != null) {
        method.invoke(parameters, latchedOrientation);
    }

} catch(Throwable t) {
    // if < 2.0
    parameters.set("rotation", latchedOrientation);
}

preview.camera.setParameters(parameters);
Run Code Online (Sandbox Code Playgroud)

NexusOne(OS 2.2) - 效果很好.latchedOrientation = 0,图片OK在EXIF标题中没有任何旋转.

T-Mobile G1(OS 1.6) - 也很棒.latchedOrientation = 0,图片确定.

摩托罗拉Backflip(OS 1.5) - 图像旋转.latchedOrientation = 0,图片中没有EXIF旋转.

Motorola CLIQ(OS 1.5) - 图像旋转.latchedOrientation = 0,图片中没有EXIF旋转.

这些摩托罗拉设备发生了什么变化?我认为我的问题是摩托罗拉相机驱动程序没有旋转图像,所以找到了Android的Sanselan EXIF阅读课,并准备自己旋转它们.有趣的是,有EXIF标题但没有旋转元素.

如果我手动将旋转设置为90度,那么图像就会完美地展现出摩托罗拉设备,但现在G1和NexusOne的图像旋转了90度(不是我想要的).必须有一些我没有到达的地方.

我怀疑这是1.5问题,否则有人会在上面发布信息?

Ruk*_*ias 46

我有这个问题,我使用这种方法来捕捉图像.(无需创建自定义相机)

final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
startActivityForResult(intent, 0);
Run Code Online (Sandbox Code Playgroud)

并在onActivityResult中完成了其余的工作(int requestCode,int resultCode,Intent data){}

但原始图像(实际SD卡图像)是正确的,当我这样取出时,位图被旋转.位图bmp = BitmapFactory.decodeStream(..

解决方案:

    try {
        File f = new File(SD_CARD_IMAGE_PATH);
        ExifInterface exif = new ExifInterface(f.getPath());
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

        int angle = 0;

        if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
            angle = 90;
        } 
        else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
            angle = 180;
        } 
        else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
            angle = 270;
        }

        Matrix mat = new Matrix();
        mat.postRotate(angle);

        Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, null);
        Bitmap correctBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);                 
    }
    catch (IOException e) {
        Log.w("TAG", "-- Error in setting image");
    }   
    catch(OutOfMemoryError oom) {
        Log.w("TAG", "-- OOM Error in setting image");
    }
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案,我只是改进了一点,因为在`angle = 0`的情况下,没有必要解码它并创建一个旋转为0的第二个位图.如果在不受影响的设备上运行,此过程减少50%的内存消耗. (6认同)

Err*_*454 10

这实际上是一个特定于设备的问题,主要影响摩托罗拉设备.谷歌开发者在API 8中包含了一个setDisplayOrientation调用来解决这个问题.主要的错误是在这里提交的.

对于那些无法进入API 8的人来说,两种常见的解决方案是:


在顶级ViewGroup中覆盖onDraw Override onDraw并将画布旋转90度以补偿旋转.请注意,此处有一个警告,因为您的触摸事件也需要旋转.

使用横向模式
将活动锁定为横向模式,但绘制资源就像是纵向模式一样.这意味着您可以进行布局并将图像资源旋转为看起来像是处于纵向模式,以便视图看起来正常.遗憾的是,由于菜单将水平打开,因此很难使用菜单.

我也看到人们使用动画控制器来旋转视图.我无法克服的缺点是旋转的视图不会伸展以填满屏幕.请参阅Georg答案,了解实施示例.