Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android上旋转YUV字节数组_Android_Rotation_Bytearray_Yuv - Fatal编程技术网

在Android上旋转YUV字节数组

在Android上旋转YUV字节数组,android,rotation,bytearray,yuv,Android,Rotation,Bytearray,Yuv,我正在寻找旋转一个YUV帧预览,这个预览来自一个叫Black的预览,到目前为止,我已经创建了这篇文章,它包含了一个旋转帧预览的算法,但是却弄乱了预览图像 另一种旋转图像的方法是从YUV图像中创建jpg,创建位图,旋转位图并获得位图的字节数组,但我确实需要YUV(NV21)格式 仅供参考。我问这个问题的原因是因为我有一个支持旋转的相机应用程序,但是帧预览只在横向模式下返回。以下方法可以将YUV420字节数组旋转90度 private byte[] rotateYUV420Degree90(byt

我正在寻找旋转一个YUV帧预览,这个预览来自一个叫Black的预览,到目前为止,我已经创建了这篇文章,它包含了一个旋转帧预览的算法,但是却弄乱了预览图像

另一种旋转图像的方法是从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;
}
专用字节[]旋转UV420degree90(字节[]数据,int-imageWidth,int-imageHeight)
{
字节[]yuv=新字节[imageWidth*imageHeight*3/2];
//旋转Y-luma
int i=0;
对于(int x=0;x=0;y--)
{
yuv[i]=数据[y*图像宽度+x];
i++;
}
}
//旋转U和V颜色组件
i=图像宽度*图像高度*3/2-1;
对于(int x=imageWidth-1;x>0;x=x-2)
{
对于(int y=0;y
(请注意,只有当宽度和高度是4的一个系数时,这可能才起作用)

下面是我如何做到的

这段代码是在别处设置的

    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);

以下是转弯的选项(90、180、270):

公共静态字节[]旋转UV420degree90(字节[]数据,int-imageWidth,int-imageHeight){
字节[]yuv=新字节[imageWidth*imageHeight*3/2];
//旋转Y-luma
int i=0;
对于(int x=0;x=0;y--){
yuv[i]=数据[y*图像宽度+x];
i++;
}
}
//旋转U和V颜色组件
i=图像宽度*图像高度*3/2-1;
对于(int x=imageWidth-1;x>0;x=x-2){
对于(int y=0;y=0;i--){
yuv[计数]=数据[i];
计数++;
}
i=图像宽度*图像高度*3/2-1;
对于(i=imageWidth*imageHeight*3/2-1;i>=imageWidth
*图像高度;i-=2){
yuv[count++]=数据[i-1];
yuv[count++]=数据[i];
}
返回yuv;
}
公共静态字节[]旋转UV420DEGREE270(字节[]数据,int-imageWidth,
int图像高度){
字节[]yuv=新字节[imageWidth*imageHeight*3/2];
int nWidth=0,nHeight=0;
int-wh=0;
int uvHeight=0;
if(imageWidth!=nWidth | | imageHeight!=nHeight){
nWidth=图像宽度;
nHeight=图像高度;
wh=图像宽度*图像高度;
uvHeight=imageHeight>>1;//uvHeight=height/2
}
//??Y
int k=0;
对于(int i=0;i
我也遇到了这个问题,最后使用了您提到的解决方案,使用
位图
旋转图像,而使用JPEG。实际上,设置显示方向不会影响文档中提到的PreviewCallback接收到的缓冲区:这不会影响PreviewFrame(byte[],Camera)、JPEG图片或录制的视频.Hi上传入的字节数组顺序。你解决了这个问题吗?非常感谢。谢谢。它真的帮助了我!但是,当我将此代码片段应用于图像旋转到(-90)的数据字节时,我遇到了一个小问题。我想旋转到+90。或者简单地说,需要反向旋转,请你帮我出来谢谢@Usama:你找到了另一种方法来旋转它吗?我也被困在这里了。谢谢。是的,我三次调用相同的函数,将返回数据作为参数传递给下一次调用,并交换宽度-高度参数。图像顺时针旋转90度,但颜色不匹配。我怀疑我收到的缓冲区(来自外部库)是否为YUV。如果我将接收到的缓冲区直接转储到文件中,并使用ffplay播放其播放精细的ffplay-v info-f rawvideo-video_size 320x240 yuv.bin,这可能会导致伪影,并且速度会很慢,因为有一个额外的JPEG编码/解码步骤。除了测试之外,不推荐其他任何东西。太慢了,请参见上面的Sami注释。它易于实现和理解,因此比其他答案更易于部署。这比绝对最佳解决方案稍微慢一点,但对于一生中只能旋转一次的图像,这是完全可以接受的
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);
}