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.
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)
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); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With