DirectShow 보유 DIB 의 조작 GetVideoInfoParameters 헬퍼-함수   [목차열람] [주소복사] [슬롯비우기]
GetVideoInfoParameters 헬퍼-함수
 
Microsoft DirectX 9.0

GetVideoInfoParameters 헬퍼-함수

비디오 이미지를 디코드하는 경우나, 이미 디코드된 비디오 이미지를 변경하는 경우는, 보폭과 이미지의 방향의 양쪽 모두를 고려할 필요가 있다. 여기에서는, 비트 맵내의 픽셀을, 일정한 방법으로 용이하게 루프 처리할 수 있도록 해주는 헬퍼-함수에 대해 설명한다.

이 함수는 다음과 같이 선언된다.

void GetVideoInfoParameters(
    const VIDEOINFOHEADER *pvih, // VIDEOINFOHEADER 의 포인터
    BYTE * const pbData,         // 버퍼의 선두의 포인터.
    bool bYuv,                   // YUV 포맷의 경우는 true 
    DWORD *pdwWidth,             // 이미지의 폭 (픽셀 단위)을 받는다
    DWORD *pdwHeight,            // 이미지의 높이 (픽셀 단위)를 받는다
    LONG *plStrideInBytes,       // 보폭 (바이트 단위)을 받는다
    BYTE **ppbTop                // 이미지의 최초의 행의 포인터를 받는다.
);

입력으로는, 이 함수는 3 개의 정보를 취한다. 비트 맵을 나타내는 VIDEOINFOHEADER 구조체의 포인터 (pvih), 비트 맵 데이터를 보관 유지하는 버퍼의 주소 (pbData), 및 비트 맵이 YUV 포맷인지, RGB 포맷인지를 나타내는 불형 플래그 (bYuv)이다.

출력으로는, 이 함수는 다음의 정보를 돌려준다.

ppbTop 로 돌려받는 값은, 항상, 화면에 표시될 때의 이미지의 좌상구석이다. 탑 다운 DIB 에서는, 이것은 메모리의 최초의 바이트이지만, 바텀 업 DIB 에서는, 최상정도행은 메모리내의 마지막에 배치된다.

plStrideinBytes 로 돌려받는 값은, 어느 행의 선두로부터 1 개하의 행의 선두까지의 바이트 오프셋(offset)이다. 따라서, 위로부터 2 번째의 행의 주소는 pbTop + lStrideInBytes 이다.

다음 코드는, 32 비트 RGB DIB 에서의 이 함수의 사용법을 나타내고 있다.

HRESULT WriteToBuffer_RGB32(BYTE *pData, VIDEOINFOHEADER *pVih)
{
    DWORD dwWidth, dwHeight;
    long lStride;
    BYTE *pbTop;
    GetVideoInfoParameters(pVih, pData, &dwWidth, 
        &dwHeight, &lStride, &pbTop, false);

    // 픽셀의 최상정도행으로부터 최하정도행까지 루프 한다.
    for (DWORD y = 0; y < dwHeight; y++)
    {
        // 은행내의 각 픽셀을 왼쪽에서 오른쪽으로 루프 한다.
        RGBQUAD *pPixel = (RGBQUAD*) pbRow;
        for (DWORD x = 0; x < dwWidth; x++)
        {
            // pPixel[x] 하행내의 x 번째의 픽셀이다.
            pPixel[x]. rgbBlue = blue value;
            pPixel[x]. rgbGreen = green value;
            pPixel[x]. rgbRed = red value;
            pPixel[x]. rgbReserved = 0;
        }
        // pbTop 를 보폭 단위로 진행한다.
        pbTop += lStride;
    }
}

외측의 루프는, 최상정도행으로부터 최하정도행까지 이동한다. 안쪽의 루프는, 각 행의 왼쪽에서 오른쪽으로 이동한다. 32 비트 RGB 비트 맵의 경우, 각 픽셀은 RGBQUAD 값으로 주소 지정된다. 그 외의 포맷은 다른 바이트 레이아웃을 사용한다.

다음 코드는, 완전한 GetVideoInfoParameters 함수를 나타내고 있다.

void GetVideoInfoParameters(
    const VIDEOINFOHEADER *pvih, // 포맷 헤더의 포인터.
    BYTE  * const pbData,   // 버퍼내의 최초의 주소의 포인터.
    bool bYuv      // 이것은 YUV 포맷화?  (true = YUV, false = RGB)
    DWORD *pdwWidth,        // 폭 (픽셀 단위)을 돌려준다.
    DWORD *pdwHeight,       // 높이 (픽셀 단위)를 돌려준다.
    LONG  *plStrideInBytes, // 새로운 행을 내리기 위해서(때문에) 행에 이것을 추가한다.
    BYTE **ppbTop,          // 픽셀의 최상정도행의 최초의 바이트의 포인터를
                            // 돌려준다.
    )
{
    LONG lStride;

    //  '표준'의 포맷의 경우, biWidth 는 픽셀 단위이다.  
    //  바이트에 확장해, 4 의 배수에 끝맺는다.
    if ((pvih->bmiHeader.biBitCount != 0) &&
        (0 == (7 & pvih->bmiHeader.biBitCount))) 
    {
        lStride = (pvih->bmiHeader.biWidth * (pvih->bmiHeader.biBitCount / 8) + 3) & ~3;
    } 
    else   // 그 이외의 경우는, biWidth 는 바이트 단위이다.
    {
        lStride = pvih->bmiHeader.biWidth;
    }

    //  rcTarget 가 비어있으면 이미지 전체를 사용한다.
    if (IsRectEmpty(&pvih->rcTarget)) 
    {
        *pdwWidth = (DWORD) pvih->bmiHeader.biWidth;
        *pdwHeight = (DWORD)(abs(pvih->bmiHeader.biHeight));
        
        if (pvih->bmiHeader.biHeight < 0 || bYuv)   // 탑 다운 비트 맵.  
        {
            *plStrideInBytes = lStride; // 보폭은 "아래" 로 향한다.
            *ppbTop           = pbData; // 최상정도행이 최초이다.
        } 
        else        // 바텀 업 비트 맵.
        {
            *plStrideInBytes = -lStride;    // 보폭은 "위" 로 향한다.
            // 최하정도행이 최초이다.
            *ppbTop = pbData + lStride * (*pdwHeight - 1);  
        }
    } 
    else   // rcTarget는 비어있지 않다.  이미지내의 서브 직사각형을 사용한다.
    {
        *pdwWidth = (DWORD)(pvih->rcTarget.right - pvih->rcTarget.left);
        *pdwHeight = (DWORD)(pvih->rcTarget.bottom - pvih->rcTarget.top);
        
        if (pvih->bmiHeader.biHeight < 0 || bYuv)   // 탑 다운 비트 맵.
        {
            // 위와 같은 보폭이지만, 최초의 픽셀이 타겟 직사각형에 의해,
            // 다음과 같이 변경되고 있다.
            *plStrideInBytes = lStride;     
            *ppbTop = pbData +
                     lStride * pvih->rcTarget.top +
                     (pvih->bmiHeader.biBitCount * pvih->rcTarget.left) / 8;
        } 
        else  // 바텀 업 비트 맵.
        {
            *plStrideInBytes = -lStride;
            *ppbTop = pbData +
                     lStride * (pvih->bmiHeader.biHeight - pvih->rcTarget.top - 1) +
                     (pvih->bmiHeader.biBitCount * pvih->rcTarget.left) / 8;
        }
    }
}

참조

↑TOP