Rotate an YUV byte array on Android

匿名 (未验证) 提交于 2019-12-03 02:11:02

问题:

I'm looking to rotate a YUV frame preview recieved from a Preview Callblack, so far I've founded this post which cointains an algorithm to rotate the frame preview but is messing the preview image camera pixels rotated

another way to rotate the image will be creating a jpg out of the YUV image, create a bitmap, rotate a bitmap and obtaining the byte array of the bitmap, but I really need the format in YUV (NV21).

FYI. the reason I'm asking this is because I have a camera app that supports rotation, but the frame previews are coming back in landscape mode only.

回答1:

The following method can rotate a YUV420 byte array by 90 degree.

private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight)  {     byte [] yuv = new byte[imageWidth*imageHeight*3/2];     // Rotate the Y luma     int i = 0;     for(int x = 0;x < imageWidth;x++)     {         for(int y = imageHeight-1;y >= 0;y--)                                        {             yuv[i] = data[y*imageWidth+x];             i++;         }     }     // Rotate the U and V color components      i = imageWidth*imageHeight*3/2-1;     for(int x = imageWidth-1;x > 0;x=x-2)     {         for(int y = 0;y < imageHeight/2;y++)                                         {             yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+x];             i--;             yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+(x-1)];             i--;         }     }     return yuv; } 

(Note that this might only work if the width and height is a factor of 4)



回答2:

Here are the options to turn a different corner (90, 180, 270):

public static byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) {     byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];     // Rotate the Y luma     int i = 0;     for (int x = 0; x < imageWidth; x++) {         for (int y = imageHeight - 1; y >= 0; y--) {             yuv[i] = data[y * imageWidth + x];             i++;         }     }     // Rotate the U and V color components     i = imageWidth * imageHeight * 3 / 2 - 1;     for (int x = imageWidth - 1; x > 0; x = x - 2) {         for (int y = 0; y < imageHeight / 2; y++) {             yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];             i--;             yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth)                     + (x - 1)];             i--;         }     }     return yuv; }  private static byte[] rotateYUV420Degree180(byte[] data, int imageWidth, int imageHeight) {     byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];     int i = 0;     int count = 0;     for (i = imageWidth * imageHeight - 1; i >= 0; i--) {         yuv[count] = data[i];         count++;     }     i = imageWidth * imageHeight * 3 / 2 - 1;     for (i = imageWidth * imageHeight * 3 / 2 - 1; i >= imageWidth             * imageHeight; i -= 2) {         yuv[count++] = data[i - 1];         yuv[count++] = data[i];     }     return yuv; }  public static byte[] rotateYUV420Degree270(byte[] data, int imageWidth,                                      int imageHeight) {     byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];     int nWidth = 0, nHeight = 0;     int wh = 0;     int uvHeight = 0;     if (imageWidth != nWidth || imageHeight != nHeight) {         nWidth = imageWidth;         nHeight = imageHeight;         wh = imageWidth * imageHeight;         uvHeight = imageHeight >> 1;// uvHeight = height / 2     }     // ??Y     int k = 0;     for (int i = 0; i < imageWidth; i++) {         int nPos = 0;         for (int j = 0; j < imageHeight; j++) {             yuv[k] = data[nPos + i];             k++;             nPos += imageWidth;         }     }     for (int i = 0; i < imageWidth; i += 2) {         int nPos = wh;         for (int j = 0; j < uvHeight; j++) {             yuv[k] = data[nPos + i];             yuv[k + 1] = data[nPos + i + 1];             k += 2;             nPos += imageWidth;         }     }     return rotateYUV420Degree180(yuv, imageWidth, imageHeight); } 


回答3:

Here's how I did it

This block of code is setup elsewhere

    Camera.Size size     Rect rectangle = new Rect();     rectangle.bottom = size.height;     rectangle.top = 0;     rectangle.left = 0;     rectangle.right = size.width; 

This is the method that does the work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!