// RGB 값을 얻기위한 YUV 테이블을 만든다.
// YUV_B, YUV_R, YUV_G 배열은 사용하기 전에 YUV_lookup_table() 함수로 초기화해야 한다.

double YY[256], BU[256], GV[256], GU[256], RV[256];
unsigned char YUV_B[256][256];
unsigned char YUV_R[256][256];
unsigned char YUV_G[256][256][256];

void YUV_lookup_table()
{
    int i, j, k;
    double i_value;
    for( i=255; i>=0; i-- )
    {
        YY[i] = (1.164*(i-16.0));
        BU[i] = (2.018*(i-128.0));
        GV[i] = (0.831*(i-128.0));
        GU[i] = (0.391*(i-128.0));
        RV[i] = (1.596*(i-128.0));
    }

    for( i=255; i>=0; i-- ){
        for( j=255; j>=0; j-- )
        {
            i_value = YY[i] + BU[j];
            if ( i_value > 255 ) i_value=255;
            else if ( i_value < 0 ) i_value=0;
            YUV_B[i][j]=(int)i_value;

            i_value = YY[i] + RV[j];
            if ( i_value > 255 ) i_value=255;
            else if ( i_value < 0 ) i_value=0;
            YUV_R[i][j]=(int)i_value;
            for( k=0; k<256; k++ )
            {
                i_value = YY[i] - (GU[j] + GV[k]);
                if ( i_value > 255 ) i_value=255;
                else if ( i_value < 0 ) i_value=0;
                YUV_G[i][j][k] =(int)i_value;
            }
        }
    }
}

// YUV 영상을 RGB 영상으로 바꾸는 함수
void yuv420_to_rgb( unsigned char *in, unsigned char *out, int w, int h )
{
    int x,y;
    double imgsize = w*h;
    int w3 = w*3;
    double uvsize = imgsize/4.0;

    unsigned char *pY = in;
    unsigned char *pV = in + (int)imgsize;
    unsigned char *pU = in + (int)imgsize + (int)uvsize;

    int y00, y01, y10, y11;
    int u,v;    
    unsigned char *p;

   // 윈도우에서는 영상의 상하가 거꾸로 저장되지 때문에 아래와 같이 코드 작성.
    for( y=0; y<=h-2; y+=2 )
    {
        for( x=0; x<=w-2; x+=2 )
        {
            p = out + w3*(h-y-1) + x*3;
            u = *pU;
            v = *pV;

            y00 = *pY;
            y01 = *(pY+1);
            y10 = *(pY+w);
            y11 = *(pY+w+1);

            *(p)        = YUV_B[y00][u];
            *(p+1)      = YUV_G[y00][u][v];
            *(p+2)      = YUV_R[y00][v];

            *(p+3)      = YUV_B[y01][u];
            *(p+3+1)    = YUV_G[y01][u][v];
            *(p+3+2)    = YUV_R[y01][v];

            *(p-w3)     = YUV_B[y10][u];
            *(p-w3+1)   = YUV_G[y10][u][v];
            *(p-w3+2)   = YUV_R[y10][v];

            *(p-w3+3)   = YUV_B[y11][u];
            *(p-w3+3+1) = YUV_G[y11][u][v];
            *(p-w3+3+2) = YUV_R[y11][v];
            
            pU++;
            pV++;
            pY = pY + 2;
        }
        pY = pY + w;
    }

    // 일반적인 경우 아래의 코드 사용함.
    /*for( y=0; y<=h-2; y+=2 )
    {
        for( x=0; x<=w-2; x+=2 )
        {
            p = out + w3*y + x*3;
            u = *pU;
            v = *pV;

            y00 = *pY;
            y01 = *(pY+1);
            y10 = *(pY+w);
            y11 = *(pY+w+1);

            *(p)        = YUV_B[y00][u];
            *(p+1)      = YUV_G[y00][u][v];
            *(p+2)      = YUV_R[y00][v];

            *(p+3)      = YUV_B[y01][u];
            *(p+3+1)    = YUV_G[y01][u][v];
            *(p+3+2)    = YUV_R[y01][v];

            *(p+w3)     = YUV_B[y10][u];
            *(p+w3+1)   = YUV_G[y10][u][v];
            *(p+w3+2)   = YUV_R[y10][v];

            *(p+w3+3)   = YUV_B[y11][u];
            *(p+w3+3+1) = YUV_G[y11][u][v];
            *(p+w3+3+2) = YUV_R[y11][v];
            
            pU++;
            pV++;
            pY = pY + 2;
        }
        pY = pY + w;
    }*/
}


//////////////////////////////////////////////////////////////////////////////////////
// BMP 파일로 저장하기

        int rgbSize = _imageSize.cx*_imageSize.cy*3;
        BYTE* pRgb = new BYTE[rgbSize];
        memset(pRgb, 0, rgbSize);

        yuv420_to_rgb(_pImage, pRgb, _imageSize.cx, _imageSize.cy);

        /*TCHAR curDirPath[512];
        ::GetModuleFileName(NULL, curDirPath, 512);
        TCHAR* pExt = _tcsrchr(curDirPath, _T('\\'));
        if(pExt) *pExt = 0;*/

        TCHAR defExt[] = _T("bmp");
        TCHAR filters[] = _T("bmp Files(*.bmp)|*.bmp|All Files(*.*)|*.*||");
        DWORD flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
        TCHAR cd[_MAX_PATH];
        GetCurrentDirectory(_MAX_PATH, cd);

        CFileDialog dlg(FALSE, defExt, 0, flags, filters, this);
        dlg.m_ofn.lpstrInitialDir = cd;        
        if(IDOK == dlg.DoModal()){
            HANDLE hFile;
            hFile = CreateFile(dlg.GetPathName(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
            if (hFile == INVALID_HANDLE_VALUE){ 
                CString s; s.Format(_T("Could not create file : %s (error %d)\n"), dlg.GetPathName(), GetLastError());
                AfxMessageBox(s, MB_ICONSTOP|MB_OK);
                return;
            }

            int headerSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD);
            BITMAPFILEHEADER fileHeader = { ((WORD)('M'<<8)|'B'), headerSize + rgbSize, 0, 0,  headerSize};
            BITMAPINFOHEADER infoHeader = { sizeof(BITMAPINFOHEADER), _imageSize.cx, _imageSize.cy, 1, 24, BI_RGB, rgbSize, 0, 0, 0, 0 };
            RGBQUAD rgbQuad = { 0, };

            DWORD writtenLen = 0;
            if(FALSE == WriteFile(hFile, &fileHeader, sizeof(fileHeader), &writtenLen, 0)){
                CString s; s.Format(_T("Could not write file : %s (error %d)\n"), _T("File Header"), GetLastError());
                AfxMessageBox(s, MB_ICONSTOP|MB_OK);
            }

            if(FALSE == WriteFile(hFile, &infoHeader, sizeof(infoHeader), &writtenLen, 0)){
                CString s; s.Format(_T("Could not write file : %s (error %d)\n"), _T("Info Header"), GetLastError());
                AfxMessageBox(s, MB_ICONSTOP|MB_OK);
            }

            if(FALSE == WriteFile(hFile, &rgbQuad, sizeof(rgbQuad), &writtenLen, 0)){
                CString s; s.Format(_T("Could not write file : %s (error %d)\n"), _T("RGB Quad"), GetLastError());
                AfxMessageBox(s, MB_ICONSTOP|MB_OK);
            }
            
            if(FALSE == WriteFile(hFile, pRgb, rgbSize, &writtenLen, 0)){
                CString s; s.Format(_T("Could not write file : %s (error %d)\n"), dlg.GetPathName(), GetLastError());
                AfxMessageBox(s, MB_ICONSTOP|MB_OK);
            }
            CloseHandle(hFile);
        }        
        
        if(pRgb)    delete [] pRgb;

'멀티미디어 > 이미지 프로세싱' 카테고리의 다른 글

YCbCr과 YPbPr  (0) 2009.03.18
YUV420(YV12)  (0) 2009.03.18
동영상 파일끼리 PSNR 비교하는 프로그램  (0) 2009.03.18
DCT 프로그램  (0) 2009.03.18
H.264 tutoroals  (0) 2009.03.18
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,