安卓相机如何保存竖屏照片

3

我正在尝试在我的应用程序中使用相机,并希望能够在横向和纵向模式下使用它。我没有任何困难在横向模式下创建图片,但我还没有找到一个好的方法来保存纵向模式下的图片。

当我想在纵向模式下拍照时,我需要先将显示方向设置为纵向,如下所示:

switch (windowManager.getDefaultDisplay().getRotation()) {
    case android.view.Surface.ROTATION_0:
        mCamera.setDisplayOrientation(90);
        break;
    case android.view.Surface.ROTATION_90:
        mCamera.setDisplayOrientation(0);
        break;
    case android.view.Surface.ROTATION_180:
        mCamera.setDisplayOrientation(270);
        break;
    case android.view.Surface.ROTATION_270:
        mCamera.setDisplayOrientation(180);
        break;
}

但是照片仍然以横向模式保存。我找到的一个解决方案是像这样更改相机的旋转参数:

public void onOrientationChanged(int orientation) {
    if (orientation == ORIENTATION_UNKNOWN) return;
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
    android.hardware.Camera.getCameraInfo(cameraId, info);
    orientation = (orientation + 45) / 90 * 90;
    int rotation = 0;
    if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
        rotation = (info.orientation - orientation + 360) % 360;
    } else {  // back-facing camera
        rotation = (info.orientation + orientation) % 360;
    }
    mParameters.setRotation(rotation);
}

这种方法的问题在于可能只是在EXIF头中设置方向,而不实际旋转图片(这是我使用的设备的情况)。
另一种方法是在拍摄后旋转实际数据,像这样:
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(rotate);
bitmap=  Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
currentData = stream.toByteArray();

但这种方法需要花费10秒钟的时间(太长了),虽然我可以将这段代码放入AsyncTask中,但我需要在一到几秒钟后获取数据,因此我仍然需要等待。

目前为止,我还没有找到更好的解决方案。


编写一些NDK代码以执行图像旋转。 - CommonsWare
@CommonsWare我从未使用过NDK,当我查找时,建议不要使用它,除非你正在做真正密集的工作或者你非常熟悉C/C++(我从未使用过它们)。虽然我的问题与性能有关,但我觉得应该有另一种(更好的)方法来解决这个问题。我也担心NDK可能会损坏我的应用程序。 - Dennis van Opstal
1
“你正在做非常密集的工作” - 旋转一个多兆像素的图像,需要“立即使用数据”,这将被视为“非常密集的工作”。 - CommonsWare
“我想知道其他应用是如何做到的” - 他们要么使用EXIF头保存它,要么使用Java或NDK代码自己旋转图像。我不能排除使用RenderScript Compute选项进行旋转的可能性,但使用NDK的一半原因是在Java中会耗尽堆空间并且无法进行旋转,有时候会失败。RenderScript可以提高速度,但不能解决内存消耗问题。当我最终将其添加到我的(当前的)相机库中时,我考虑使用此代码:https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations。 - CommonsWare
@barmaley 我使用android.hardware.Camera类和自定义SurfaceView来显示预览。 - Dennis van Opstal
显示剩余4条评论
1个回答

2

我找到了一个解决方案,虽然仍需要等待一两秒钟,但对我来说已经足够快了。 这是一个相当简单的修复方法,只需使用Matrix.postRotate方法,但要更改:

bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

to:

bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);

对我来说,这是一个相当不错的解决方案,尤其是因为我在其他地方已经使用了 .jpg 图像,所以将 Bitmap 压缩为 .png 没有太多意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接