【问题标题】:Android Camera Saving Pictures in Portrait ModeAndroid相机以人像模式保存图片
【发布时间】:2016-09-05 06:19:10
【问题描述】:

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

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

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 我从未使用过 NDK,当我查找它时,建议不要使用它,除非您正在做非常密集的工作或者您非常熟悉 C/C++(我没有从来没有用过它们)。虽然我的问题与性能有关,但我觉得应该有另一种(更好的)方法来做到这一点。我也担心 NDK 可能会搞砸我的一些应用程序。
  • “你正在做非常密集的事情”——旋转一个数百万像素的图像,你“立即需要数据”将被视为“非常密集的事情”。
  • @CommonsWare 你可能是对的,这很激烈,但我仍然相信有更好的解决方案(也许可以让相机垂直拍摄图像,所以我不需要旋转它)。我想知道其他应用程序是如何做到的。
  • “我想知道其他应用程序是如何做到的”——它们要么使用 EXIF 标头保存它,要么使用 Java 或 NDK 代码自行旋转图像。我不能排除 RenderScript Compute 选项用于轮换的可能性,但使用 NDK 的一半原因是您将在 Java 中耗尽堆空间并且有时无法进行轮换。 RenderScript 可能有助于提高速度,但对内存消耗没有帮助。当我最终将它添加到我的(当前)相机库时,我正在考虑使用this code

标签: java android camera android-camera


【解决方案1】:

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

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

到:

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

对我来说,这是一个很好的解决方案,尤其是因为我已经在其他地方使用了 .jpg 图像,因此无论如何将位图压缩为 .png 并没有多大意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-19
    • 2012-12-20
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    相关资源
    最近更新 更多