我正在寻找旋转从 Preview Callblack 收到的 YUV 帧预览,到目前为止,我已经创建了这篇文章,其中包含一种旋转帧预览的算法,但正在弄乱 旋转的预览图像相机像素
另一种旋转图像的方法是从 YUV 图像中创建 jpg,创建位图,旋转位图并获取位图的字节数组,但我确实需要 YUV(NV21)中的格式。
供参考。我问这个的原因是因为我有一个支持旋转的相机应用程序,但帧预览仅以横向模式返回。
我正在寻找旋转从 Preview Callblack 收到的 YUV 帧预览,到目前为止,我已经创建了这篇文章,其中包含一种旋转帧预览的算法,但正在弄乱 旋转的预览图像相机像素
另一种旋转图像的方法是从 YUV 图像中创建 jpg,创建位图,旋转位图并获取位图的字节数组,但我确实需要 YUV(NV21)中的格式。
供参考。我问这个的原因是因为我有一个支持旋转的相机应用程序,但帧预览仅以横向模式返回。
以下方法可以将 YUV420 字节数组旋转 90 度。
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;
}
(请注意,这可能仅在宽度和高度为 4 的情况下才有效)
以下是转向不同拐角的选项(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);
}
我是这样做的
此代码块设置在别处
Camera.Size size
Rect rectangle = new Rect();
rectangle.bottom = size.height;
rectangle.top = 0;
rectangle.left = 0;
rectangle.right = size.width;
这是完成工作的方法
private Bitmap rotateBitmap(YuvImage yuvImage, int orientation, Rect rectangle)
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
yuvImage.compressToJpeg(rectangle, 100, os);
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
byte[] bytes = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
return Bitmap.createBitmap(bitmap, 0 , 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
将 YUVImage 压缩成 JPEG,以便位图可以处理它。旋转位图,然后将其导出。为了将它恢复为我想要的 JPEG,我使用了这条线
image.compress(Bitmap.CompressFormat.JPEG, 50, outputStream);