可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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