天天看點

設定nv12的矩形邊框

NV12

一個6*4的nv12格式的圖檔的三個分量YUV的記憶體形式:

設定nv12的矩形邊框

雖然nv12的像素大小是width*height,但是必須為nv12圖檔配置設定width*height*3/2的記憶體空間,因為Y分量所占的記憶體為width*height,而U,V分量各占width*height/4,見上圖即一目了然。

nv12分量YUV分量記憶體操作:可以用雙重for循環周遊nv12各個分量的記憶體分布,進而實作給nv12圖檔賦予不同的顔色。

由記憶體YUV分量記憶體分布圖可以知道:

0 ~ width*height 為Y分量存儲的記憶體範圍。

width*height ~ width*height*3/2 為UV交叉存儲的記憶體範圍。

操作Y分量:

buf[j * width + k]

操作U分量 :

buf[j / 2 * width + k - k % 2 + width * height]

操作V分量 :

buf[j / 2 * width + k - k % 2 + width * height + 1]

在nv12格式的圖檔上畫一個鎖定某個目标的矩形方框圖

#include <stdio.h>
#include <stdlib.h>

int nv12_border(char *pic, int pic_w, int pic_h, int rect_x, int rect_y, int rect_w, int rect_h, int R, int G, int B);

int main()
{
    /* Set up the nv12's pixel size */
    const int pic_w  = ;
    const int pic_h  = ;

    /* Set up test data's path and output data's path */
    char *inputPathname  = "/home/flypei/work/nv12-marked-rect/data/videotestsrc_1920x1080.nv12";
    char *outputPathname = "./outputFile.nv12";

    FILE *fin  = fopen(inputPathname , "rb+");
    FILE *fout = fopen(outputPathname, "wb+");

    /* Allocate memory for nv12 */
    unsigned char *buf = (unsigned char *)malloc(pic_w * pic_h *  / );

    /* Read file data to buffer */
    fread(buf, , pic_w * pic_h *  / , fin);

    /* Draw rectangle border to nv12 */
    nv12_border(buf, pic_w, pic_h, , , , , , , );

    /* Write data of buf to fout */
    fwrite(buf, , pic_w * pic_h *  / , fout);

    /* Free the allocation memory */
    free(buf);

    /* Close the file */
    fclose(fin);
    fclose(fout);

    return ;
}

int nv12_border(char *pic, int pic_w, int pic_h, int rect_x, int rect_y, int rect_w, int rect_h, int R, int G, int B)
{
    /* Set up the rectangle border size */
    const int border = ;

    /* RGB convert YUV */
    int Y, U, V;
    Y =    * R +   * G +   * B;
    U = - * R +  * G +     * B + ;
    V =      * R -  * G -  * B + ;

    /* Locking the scope of rectangle border range */
    int j, k;
    for(j = rect_y; j < rect_y + rect_h; j++){
        for(k = rect_x; k < rect_x + rect_w; k++){
            if (k < (rect_x + border) || k > (rect_x + rect_w - border) ||\
                    j < (rect_y + border) || j > (rect_y + rect_h - border)){

                /* Components of YUV's storage address index */
                int y_index = j * pic_w + k;
                int u_index = (y_index /  - pic_w /  * ((j + ) / )) *  + pic_w * pic_h;
                int v_index = u_index + ;

                /* set up YUV's conponents value of rectangle border */
                pic[y_index] =  Y ;
                pic[u_index] =  U ;
                pic[v_index] =  V ;
            }
        }
    }

    return ;
}
           

原nv12圖檔(用yuvplayer檢視):

設定nv12的矩形邊框

加上方框的nv12圖檔(用yuvplayer檢視):

設定nv12的矩形邊框

demo優化版

#include <stdio.h>
#include <stdlib.h>

#define uchar unsigned char

typedef struct rectangle{
    int x;
    int y;
    int w;
    int h;
    uchar thin;
    uchar YUV[];
}RECT;

void RgbToYuv(uchar RGB[], uchar YUV[]);
void FindAxis(RECT rect[], int n, int rect_all_axis[]);
void DrawWidthLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[]);
void DrawHeightLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[]);
void DrawPoint(uchar* pic, int pic_w, int pic_h, int point_axis[], int count, uchar YUV[]);
void NV12MarkRect(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int point_axis[], int count);

int main()
{
    /*****************************************************/
    /****                                             ****/
    /****             Configure Parameter             ****/
    /****                                             ****/
    /*****************************************************/

    /* Config the nv12's pixel size */
    const int pict_w  = ;
    const int pict_h  = ;
    int picSize = pict_w * pict_h * ;

    /* Allocate memory for nv12 */
    uchar* picBuf = (unsigned char *)malloc(picSize);

    /* RGB convert to YUV */
    uchar RGBblue[] = {, , };
    uchar YUVblue[];
    RgbToYuv(RGBblue, YUVblue);

    /* Config rectangle's quanlity and parameter */
    int n = ;
    uchar t = ;
    RECT Rect[] = {
        {
            .x = ,
            .y = ,
            .w = ,
            .h = ,
            .thin = t,
            .YUV[] = YUVblue[],
            .YUV[] = YUVblue[],
            .YUV[] = YUVblue[] },
        {
            .x = ,
            .y = ,
            .w = ,
            .h = ,
            .thin = t,
            .YUV[] = YUVblue[],
            .YUV[] = YUVblue[],
            .YUV[] = YUVblue[] }
    };

    /* Config point axis's count and draw the point at NV12 */
    int c = ;
    int point[] = { ,, ,, ,, ,, ,, ,, ,, ,, ,, ,,
                    ,, ,, ,, ,, ,, ,, ,, ,, ,, ,,
                    ,, ,, ,, ,, ,, ,, ,, ,, ,, , };

    /* Config input and output path */
    char input[]  = "videotestsrc_1920x1080.nv12";
    char output[] = "outputFile.nv12";

    /******************************************************/

    FILE *fin  = fopen(input,  "rb");
    FILE *fout = fopen(output, "wb+");

    /* Read file data to buffer */
    fread(picBuf, , picSize, fin);

    /* Draw rectangle and point to nv12 */
    NV12MarkRect(picBuf, pict_w, pict_h, Rect, n, point, c);

    /* Write data of buf to fout */
    fwrite(picBuf, , picSize, fout);

    /* Free the allocation memory */
    free(picBuf);

    /* Close the file */
    fclose(fin);
    fclose(fout);

    return ;
}

void RgbToYuv(uchar RGB[], uchar YUV[])
{
    /* RGB convert YUV */
    YUV[] =    * RGB[] +   * RGB[] +   * RGB[];
    YUV[] = - * RGB[] +  * RGB[] +     * RGB[] + ;
    YUV[] =      * RGB[] -  * RGB[] -  * RGB[] + ;
}

void FindAxis(RECT rect[], int n, int axis[])
{
    axis[] = axis[] = axis[] = rect[n].x;
    axis[] = rect[n].x + rect[n].w - rect[n].thin;
    axis[] = rect[n].y;
    axis[] = rect[n].y + rect[n].h - rect[n].thin;
    axis[] = axis[] = rect[n].y + rect[n].thin;
}

void DrawWidthLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[])
{
    int i, j, k;
    int y_index, u_index, v_index;
    for (i = ; i < ; i += ){
        for (j = axis[i+]+rect[n].thin-; j >= axis[i+]; j--){
            for (k = axis[i]+rect[n].w-; k >= axis[i]; k--){

                y_index = j * pic_w + k;
                u_index = ((j >> ) + pic_h) * pic_w + k - (k & );
                //u_index = (((y_index >> 1) - (pic_w >> 1) * ((j + 1) >> 1)) << 1) + pic_w * pic_h;
                v_index = u_index + ;

                pic[y_index] = rect[n].YUV[];
                pic[u_index] = rect[n].YUV[];
                pic[v_index] = rect[n].YUV[];

            }
        }
    }
}

void DrawHeightLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[])
{
    int i, j, k;
    int y_index, u_index, v_index;
    for (i = ; i < ; i += ){
        for (k = axis[i]+rect[n].thin-; k >= axis[i]; k--){
            for (j = axis[i+]+rect[n].h-(*rect[n].thin)-; j >= axis[i+]; j--){
                y_index = j * pic_w + k;
                u_index = ((j >> ) + pic_h) * pic_w + k - (k & );
                //u_index = (((y_index >> 1) - (pic_w >> 1) * ((j + 1) >> 1)) << 1) + pic_w * pic_h;
                v_index = u_index + ;

                pic[y_index] = rect[n].YUV[];
                pic[u_index] = rect[n].YUV[];
                pic[v_index] = rect[n].YUV[];

            }
        }
    }
}

void DrawPoint(uchar* pic, int pic_w, int pic_h, int point_axis[], int count, uchar YUV[])
{
    /* Draw points at NV12 */
    int a, y_point, u_point, v_point;
    for (a = (count-)*; a >= ; a -= ){

            y_point = point_axis[a+] * pic_w + point_axis[a];
            u_point = ((point_axis[a+] >> ) + pic_h) * pic_w + point_axis[a] - (point_axis[a] & );
            //u_point = (((y_point >> 1) - (pic_w >> 1) * ((point_axis[a+1] + 1) >> 1)) << 1) + pic_w * pic_h;
            v_point = u_point + ;

            pic[y_point] = YUV[];
            pic[u_point] = YUV[];
            pic[v_point] = YUV[];
    }

}

void NV12MarkRect(uchar* pic, int pic_w, int pic_h, RECT rect[], int num, int point_axis[], int count)
{
    int i;
    int axis[];

    for (i = num-; i >= ; i--){

        FindAxis(rect, i, axis);
        DrawWidthLine(pic, pic_w, pic_h, rect, i, axis);
        DrawHeightLine(pic, pic_w, pic_h, rect, i, axis);
    }

    DrawPoint(pic, pic_w, pic_h, point_axis, count, rect[].YUV);
}
           

繼續閱讀