YUV文件转RGB并保存为bmp格式

本文YUV文件以YUV420为例(YUV文件格式可以自行百度)。

方法一;显示在控件上没问题

   #define unsigned char  U8
   bool Yv12ToBgb24(U8* pYUV, U8* pBGR24, int width, int height)
   {
        if (width < 1 || height < 1 || pYUV == NULL || pBGR24 == NULL)
        {
            return false;
        }

        const long len = width * height;
        U8* yData = pYUV;
        U8* vData = &yData[len];
        U8* uData = &vData[len >> 2];

        int bgr[3];
        int yIdx, uIdx, vIdx, idx;
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                yIdx = i * width + j;
                vIdx = (i / 2) * (width / 2) + (j / 2);
                uIdx = vIdx;

                bgr[0] = (int)(yData[yIdx] + 1.732446 * (uData[vIdx] - 128));                                    // b分量
                bgr[1] = (int)(yData[yIdx] - 0.698001 * (uData[uIdx] - 128) - 0.703125 * (vData[vIdx] - 128));    // g分量
                bgr[2] = (int)(yData[yIdx] + 1.370705 * (vData[uIdx] - 128));                                    // r分量

                for (int k = 0; k < 3; k++)
                {
                    idx = (i * width + j) * 3 + k;
                    if (bgr[k] >= 0 && bgr[k] <= 255)
                    {
                        pBGR24[idx] = bgr[k];
                    }
                    else
                    {
                        pBGR24[idx] = (bgr[k] < 0) ? 0 : 255;
                    }        
                }
            }
        }
        return true;
   }

方法二:保存在本地没问题

bool Yuv420ToRgb(U8* pYUV, U8* pRGB, int width, int height)
        {
        if (width < 1 || height < 1 || pYUV == NULL || pRGB == NULL)
        {
            return false;
        }

        //找到Y、U、V在内存中的首地址
        U8* pY = pYUV;
        U8* pU = pYUV + height*width;
        U8* pV = pU + (height*width / 4);
        
        U8* pBGR = NULL;
        U8 R = 0;
        U8 G = 0;
        U8 B = 0;
        U8 Y = 0;
        U8 U = 0;
        U8 V = 0;
        double temp = 0;

        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                //找到相应的RGB首地址
                pBGR = pRGB + i*width * 3 + j * 3;

                //取Y、U、V的数据值
                Y = *(pY + i*width + j);
                U = *pU;
                V = *pV;
                //yuv转rgb公式
                //yuv转rgb公式
                temp = Y + ((1.773) * (U - 128));
                B = temp < 0 ? 0 : (temp>255 ? 255 : (U8)temp);

                temp = (Y - (0.344) * (U - 128) - (0.714) * (V - 128));
                G = temp < 0 ? 0 : (temp>255 ? 255 : (U8)temp);

                temp = (Y + (1.403)*(V - 128));
                R = temp < 0 ? 0 : (temp>255 ? 255 : (U8)temp);

                //将转化后的rgb保存在rgb内存中,注意放入的顺序b是最低位
                *pBGR = B;
                *(pBGR + 1) = G;
                *(pBGR + 2) = R;

                if (j % 2 != 0)
                {
                    *pU++;
                    *pV++;
                }
            }
            if (i % 2 == 0)
            {
                pU = pU - width / 2;
                pV = pV - width / 2;
            }
        }
        return true;
        }

保存bmp格式:

typedef struct MyBITMAPFILEHEADER_ST
        {
            unsigned int   bfSize;
            unsigned short bfReserved1;
            unsigned short bfReserved2;
            unsigned int   bfOffBits;
        }MyBITMAPFILEHEADER;


        typedef struct MyBITMAPINFOHEADER_ST
        {
            unsigned int   biSize;
            int            biWidth;
            int            biHeight;
            unsigned short biPlanes;
            unsigned short biBitCount;
            unsigned int   biCompression;
            unsigned int   biSizeImage;
            int            biXPelsPerMeter;
            int            biYPelsPerMeter;
            unsigned int   biClrUsed;
            unsigned int   biClrImportant;
        }MyBITMAPINFOHEADER;

保存到本地

图片保存的时候,一定要注意bih.biHeight = -height; //图片如果颠倒,去掉负号

//保存到本地
    void MySaveBmp(U8 *rgbbuf, int width, int height)
    {
        MyBITMAPFILEHEADER bfh;
        MyBITMAPINFOHEADER bih;
        unsigned short bfType = 0x4d42;
        bfh.bfReserved1 = 0;
        bfh.bfReserved2 = 0;
        bfh.bfSize = 2 + sizeof(MyBITMAPFILEHEADER) + sizeof(MyBITMAPINFOHEADER) + width*height * 3;
        bfh.bfOffBits = 0x36;

        bih.biSize = sizeof(MyBITMAPINFOHEADER);
        bih.biWidth = width;
        bih.biHeight = -height; //图片如果颠倒,去掉负号
        bih.biPlanes = 1;
        bih.biBitCount = 24;
        bih.biCompression = 0;
        bih.biSizeImage = 0;
        bih.biXPelsPerMeter = 5000;
        bih.biYPelsPerMeter = 5000;
        bih.biClrUsed = 0;
        bih.biClrImportant = 0;

        FILE* file;
        fopen_s(&file, "test11.bmp", "wb");
        if (!file)
        {
            //printf("Could not write file\n");
            return;
        }

        fwrite(&bfType, sizeof(bfType), 1, file);
        fwrite(&bfh, sizeof(bfh), 1, file);
        fwrite(&bih, sizeof(bih), 1, file);

        fwrite(rgbbuf, width*height * 3, 1, file);
        fclose(file);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WJsuperrunner

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值