YUV与RGB相互转换

Android相机yuv输出格式是420sp,MediaCodec硬编码通常也是yuv420sp,因此yuv420sp与rgb之间的转换较为常用,这里记录一下:

转换公式按照

yuv2rgb:   \\R=Y+1.403(V-128) \\ G=Y-0.344(U-128)-0.714(V-128) \\ B=Y+1.770(U-128)

 rgb2yvv:  \\Y=0.299R+0.587G+0.114B \\U=0.5R-0.419G-0.081B+128 \\V=-0.169R-0.331G+0.5B+128

rgb转yuv420sp(YYYYUVUV),每逢偶数行及偶数列取一次UV数据:

/**
     * @param yuv420sp target to save yuv data, the length should be at least width*height*1.5
     * @param rgb rgb data, every 3 bytes as a color, without alpha
     * @param width image width
     * @param height image height
     * @param stride The number of bytes to skip between rows.
     *               Normally this value will be the same as the width, but it may be larger sometimes
     */
    void rgb2YUV420sp(byte[] yuv420sp, byte[] rgb, int width, int height, int stride) {

        int frameSize = width * height;
        int yIndex = 0;
        int uvIndex = frameSize;

        int r, g, b, y, u, v;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {

                int index = (i * stride + j) * 3;
                r = rgb[index++];
                g = rgb[index++];
                b = rgb[index];

                //RGB to YUV
                y = (76 * r + 150 * g + 29 * b + 128) >> 8;//y=0.299r+0.587g+0.114b

                yuv420sp[yIndex++] = (byte) (y < 0 ? 0 : y > 255 ? 255 : y);
                if (i % 2 == 0 && j % 2 == 0) {
                    u = ((-43 * r - 84 * g + 128 * b + 128) >> 8) + 128;//u=-0.169r-0.331g+0.5b+128
                    v = ((128 * r - 107 * g - 20 * b + 128) >> 8) + 128;//v=0.5r-0.419g-0.081b+128
                    yuv420sp[uvIndex++] = (byte) (v < 0 ? 0 : v > 255 ? 255 : v);
                    yuv420sp[uvIndex++] = (byte) (u < 0 ? 0 : u > 255 ? 255 : u);
                }
            }
        }
    }

下面是yuv420sp转rgb的

/**
     * Convert image format from i420sp(NV12) to ARGB
     *
     * @param pixels array to save pixels, it's length should be no less than width*height
     * @param data   YUV data(like YYYYUVUV) with <I>length=1.5*width*height</I>,
     *               <b>or</b> gray image that has only Y plane with <I>length=width*height</I>
     * @param width  width of image
     * @param height height of image
     */
    public void convertYuv2Rgb(int[] pixels, byte[] data, int width, int height) {
        int len = width * height;
        if (len == data.length) {//only has Y
            for (int i = 0; i < len; i++) {
                int y = data[i] & 0xff;
                pixels[i] = Color.argb(255, y, y, y);
            }
        } else {
            int[] rgb = new int[3];
            int y, u, v;
            int pixIndex = 0;
            int yStart, uvStart;
            for (int i = 0; i < height; i++) {
                yStart = i * width;//use stride, if stride!=width
                //uv start from width*height, every 2 columns share 1 row of uv data with stride=width
                uvStart = len + (i >> 1) * width;
                for (int j = 0; j < width; j++) {
                    y = data[yStart + j] & 0xff;
                    int uIndex = uvStart + (j >> 1 << 1);//every 2 pixels shared a group of uv
                    u = (data[uIndex++] & 0xff) - 128;
                    v = (data[uIndex] & 0xff) - 128;
                    rgb[0] = y + (v * 359 >> 8);//r=y+1.403v
                    rgb[1] = y - (u * 88 >> 8) - (v * 182 >> 8);//g=y-0.344u-0.714v
                    rgb[2] = y + (u * 453 >> 8);//b=y+1.77u
                    for (int k = 0; k < 3; k++) {//rgb value should be 0-255
                        rgb[k] = rgb[k] > 255 ? 255 : rgb[k] < 0 ? 0 : rgb[k];
                    }
                    pixels[pixIndex++] = Color.argb(255, rgb[0], rgb[1], rgb[2]);
                }
            }
        }
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值