【问题标题】:Rotate YUV420/NV21 Image in android在 android 中旋转 YUV420/NV21 图像
【发布时间】:2014-04-16 10:38:37
【问题描述】:

在表面的 PreviewCall 中,我们在相机预览中获得了 YUV420SP 格式,但由于该图像的错误旋转,我想正确旋转 YUV 图像,因为我需要通过网络发送它。所以需要应用正确的旋转。

我发现这个链接可以正确旋转,但图像颜色变差了。

http://www.wordsaretoys.com/2013/10/25/roll-that-camera-zombie-rotation-and-coversion-from-yv12-to-yuv420planar/

还检查了Rotate an YUV byte array on Android,但它没有正确显示图像。

我确实检查了 stckoverflow 上的链接,但他们都没有关于在 android 环境中正确使用代码的令人满意的答案。

有谁知道如何正确旋转 NV21 Image bytes[] 并正确保留其颜色信息。

【问题讨论】:

  • 您在寻找本机代码还是 Java?你完全了解 YUV 平面图像的格式吗?亮度平面在前面,然后是色度平面。

标签: android image-processing rotation yuv


【解决方案1】:

如果您只想旋转 NV21,以下代码会有所帮助。 (我修改了代码from here

public static void rotateNV21(byte[] input, byte[] output, int width, int height, int rotation) {
        boolean swap = (rotation == 90 || rotation == 270);
        boolean yflip = (rotation == 90 || rotation == 180);
        boolean xflip = (rotation == 270 || rotation == 180);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int xo = x, yo = y;
                int w = width, h = height;
                int xi = xo, yi = yo;
                if (swap) {
                    xi = w * yo / h;
                    yi = h * xo / w;
                }
                if (yflip) {
                    yi = h - yi - 1;
                }
                if (xflip) {
                    xi = w - xi - 1;
                }
                output[w * yo + xo] = input[w * yi + xi];
                int fs = w * h;
                int qs = (fs >> 2);
                xi = (xi >> 1);
                yi = (yi >> 1);
                xo = (xo >> 1);
                yo = (yo >> 1);
                w = (w >> 1);
                h = (h >> 1);
                // adjust for interleave here
                int ui = fs + (w * yi + xi) * 2;
                int uo = fs + (w * yo + xo) * 2;
                // and here
                int vi = ui + 1;
                int vo = uo + 1;
                output[uo] = input[ui]; 
                output[vo] = input[vi]; 
            }
        }
    }   

【讨论】:

  • 这似乎适用于 180 度,但旋转 90 度和 270 度会使图像失真。
  • 我试了270度,发现图片大小静止的问题。
  • 同意图片失真请更新您的代码为 90 度。
【解决方案2】:

Eddy Yong 的代码仅适用于 180 度,但在此处获得了一些支持,并且在其他 SO 主题和其他类似主题(例如 github 讨论)中获得了很多复制粘贴,所以我决定离开这里适当未来研究人员的答案,以及适用于 90、180 和 270 度的旋转方法

public static byte[] rotateNV21(final byte[] yuv,
                                final int width,
                                final int height,
                                final int rotation)
{
  if (rotation == 0) return yuv;
  if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
    throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0");
  }

  final byte[]  output    = new byte[yuv.length];
  final int     frameSize = width * height;
  final boolean swap      = rotation % 180 != 0;
  final boolean xflip     = rotation % 270 != 0;
  final boolean yflip     = rotation >= 180;

  for (int j = 0; j < height; j++) {
    for (int i = 0; i < width; i++) {
      final int yIn = j * width + i;
      final int uIn = frameSize + (j >> 1) * width + (i & ~1);
      final int vIn = uIn       + 1;

      final int wOut     = swap  ? height              : width;
      final int hOut     = swap  ? width               : height;
      final int iSwapped = swap  ? j                   : i;
      final int jSwapped = swap  ? i                   : j;
      final int iOut     = xflip ? wOut - iSwapped - 1 : iSwapped;
      final int jOut     = yflip ? hOut - jSwapped - 1 : jSwapped;

      final int yOut = jOut * wOut + iOut;
      final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1);
      final int vOut = uOut + 1;

      output[yOut] = (byte)(0xff & yuv[yIn]);
      output[uOut] = (byte)(0xff & yuv[uIn]);
      output[vOut] = (byte)(0xff & yuv[vIn]);
    }
  }
  return output;
}

originally posted by jake in this SO topic

【讨论】:

    猜你喜欢
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 2014-10-26
    • 2015-11-04
    • 2011-07-20
    相关资源
    最近更新 更多