3

我想将 YUV420SP 图像逆时针旋转 90。图像大小为 640*480,因此旋转后的图像大小变为 480*640,这是我不想要的,所以我想提取 480*480 数据(或任何其他正方形大小)并旋转该数据。

我见过:Rotate an YUV byte array on Android

但是这个答案顺时针旋转了 90 度。

有人可以建议一些将 YUV420Sp 数据旋转 90(逆时针)或 270 度(顺时针)而不改变图像尺寸的功能。

4

1 回答 1

5

好的,这是我的本机代码,经过多次撞击后演变而来。

我的困难是直到我看到这个和这个,我才理解平面图像格式:

YUV420SP NV21 图像格式

以下是我最终编写的 2 个函数:

// rotate luma image plane 90*
//
//             (dst direction)
//                 ------>
//      dst -> +-------------+
//             |^            |
//             |^ (base dir) |
//             |^            |
//     base -> +-------------+ <- endp
//
//////////////////////////////////////////////////////////
void rotateLumaPlane90(const unsigned char *src, unsigned char *dst,
                       size_t size, size_t width, size_t height)
{
    const unsigned char *endp;
    const unsigned char *base;
    int j;

    endp = src + size;
    for (base = endp - width; base < endp; base++) {
        src = base;
        for (j = 0; j < height; j++, src -= width)
        {
            *dst++ = *src;
        }

    }
}


//
// nv12 chroma plane is interleaved chroma values that map
// from one pair of chroma to 4 pixels:
//
// Y1 Y2 Y3 Y4
// Y5 Y6 Y7 Y8   U1,V1 -> chroma values for block  Y1 Y2
// Y9 Ya Yb Yc                                     Y5 Y6
// Yd Ye Yf Yg
// -----------   U2,V2 -> chroma values for block  Y3 Y4
// U1 V1 U2 V2                                     Y7 Y8
// U3 V3 U4 V4
//
//////////////////////////////////////////////////////////
void rotateChromaPlane90(const unsigned char *src, unsigned char *dst,
                         size_t size, size_t width, size_t height)
{
    // src will start at upper right, moving down to bottom
    // then left 1 col and down...
    //
    // dest will start at end and go to 0

    int row = 0;
    int col = (int) width;
    int src_offset = col - 1;
    int dst_offset = (int) size - 2;

    while (src_offset >= 0)
    {
        dst[dst_offset] = src[src_offset];
        dst[dst_offset+1] = src[src_offset+1];
        dst_offset -= 2;

        src_offset += width;
        row++;

        if (row >= height) {
            col -= 2;
            src_offset = col;
            row = 0;
        }
    }
}

这是我从 android native 调用这些函数的示例:

  // first rotate the Y plane
  rotateLumaPlane90((unsigned char *) encode_buffer, 
                     rotate_buffer, 
                     yPlaneSize,
                     gInputWidth, 
                     gInputHeight);


  // now rotate the U and V planes
  rotateChromaPlane90((unsigned char *) encode_buffer + yPlaneSize,
                       rotate_buffer + yPlaneSize,
                       yPlaneSize / 2,
                       gInputWidth,
                       gInputHeight/2);

注意最后一个参数rotateChromaPlane90是原始图像/2 的高度。我可能应该只更改色度旋转功能以减少出错的可能性。

当翻转到后置摄像头时,我发现我需要在相反方向(或 270*)旋转 90*,所以我也有 270* 的变化:

// rotate luma image plane 270*
//
//             +-------------+
//             |^            |
//             |^ (base dir) |
//             |^            |
//     base -> +-------------+ <- endp
//                          ^
//             <----------  |
//              (dst dir)  dst
//
//////////////////////////////////////////////////////////
void rotateLumaPlane270(unsigned char *src,
                        register unsigned char *dst,
                        int size, int width, int height)
{
    unsigned char *endp;
    register unsigned char *base;
    int j;

    endp = src + size;
    dst = dst + size - 1;
    for (base = endp - width; base < endp; base++) {
        src = base;
        for (j = 0; j < height; j++, src -= width)
        {
            *dst-- = *src;
        }

    }
}

//
// nv21 chroma plane is interleaved chroma values that map
// from one pair of chroma to 4 pixels:
//
// Y1 Y2 Y3 Y4
// Y5 Y6 Y7 Y8   U1,V1 -> chroma values for block  Y1 Y2
// Y9 Ya Yb Yc                                     Y5 Y6
// Yd Ye Yf Yg
// -----------   U2,V2 -> chroma values for block  Y3 Y4
// U1 V1 U2 V2                                     Y7 Y8
// U3 V3 U4 V4
//
//////////////////////////////////////////////////////////
void rotateChromaPlane270(unsigned char *src,
                          register unsigned char *dst,
                          int size, int width, int height)
{
    // src will start at upper right, moving down to bottom
    // then left 1 col and down...
    //
    // dest will start at 0 and go til end

    int row = 0;
    int col = width;
    int src_offset = col - 1;
    int dst_offset = 0;

    while (src_offset > 0)
    {
      dst[dst_offset++] = src[src_offset];
      dst[dst_offset++] = src[src_offset+1];

      src_offset += width;
      row++;

      if (row >= height) {
        col -= 2;
        src_offset = col;
        row = 0;
      }
    }
}
于 2015-08-18T18:05:47.497 回答