그림 가로 세로 비율
이 항목에서는 그림 가로 세로 비율과 픽셀 가로 세로 비율의 두 가지 관련 개념에 대해 설명합니다. 그런 다음 미디어 형식을 사용하여 Microsoft Media Foundation에서 이러한 개념을 표현하는 방법을 설명합니다.
그림 가로 세로 비율
그림 가로 세로 비율 은 표시된 비디오 이미지의 모양을 정의합니다. 그림 가로 세로 비율은 X:Y로 표기되어 있습니다. 여기서 X:Y는 그림 너비와 그림 높이의 비율입니다. 대부분의 비디오 표준은 4:3 또는 16:9 그림 가로 세로 비율을 사용합니다. 16:9 가로 세로 비율은 일반적으로 와이드스크린이라고합니다. 영화 영화는 종종 1:85:1 또는 1:66:1 가로 세로 비율을 사용합니다. 그림 가로 세로 비율을 DAR(표시 가로 세로 비율)라고도 합니다.
경우에 따라 비디오 이미지의 모양이 표시 영역과 같지 않은 경우가 있습니다. 예를 들어 4:3 비디오는 와이드스크린(16×9) 텔레비전에 표시될 수 있습니다. 컴퓨터 비디오에서는 임의 크기가 있는 창 내에 비디오가 표시될 수 있습니다. 이 경우 표시 영역에 맞게 이미지를 만들 수 있는 세 가지 방법이 있습니다.
- 이미지를 한 축을 따라 늘이면 표시 영역에 맞습니다.
- 원래 그림 가로 세로 비율을 기본 표시 영역에 맞게 이미지 크기를 조정합니다.
- 이미지를 자세요.
올바른 그림 가로 세로 비율을 유지하지 않으므로 표시 영역에 맞게 이미지를 늘이는 것은 거의 항상 잘못된 것입니다.
레터 박스
4:3 디스플레이에 맞게 와이드스크린 이미지의 크기를 조정하는 프로세스를 다음 다이어그램에 표시된 레터박싱이라고 합니다. 이미지의 위쪽과 아래쪽에 있는 결과 사각형 영역은 일반적으로 검은색으로 채워지지만 다른 색을 사용할 수 있습니다.
와이드스크린 디스플레이에 맞게 4:3 이미지의 크기를 조정하는 역방향 사례를 필러박싱이라고도 합니다. 그러나 레터박스라는 용어는 지정된 표시 영역에 맞게 비디오 이미지의 크기를 조정하는 것을 의미하는 일반적인 의미로도 사용됩니다.
Pan-and-Scan
팬 앤 스캔은 4:3 디스플레이 장치에 표시하기 위해 와이드스크린 이미지를 4×3 사각형 영역으로 자르는 기술입니다. 결과 이미지는 검은색 레터박스 영역을 요구하지 않고 전체 디스플레이를 채우지만 원본 이미지의 일부가 그림에서 잘립니다. 잘린 영역은 관심 영역이 이동함에 따라 프레임에서 프레임으로 이동할 수 있습니다. 이동 및 검사에서 "pan"이라는 용어는 이동 및 검색 영역 이동으로 인해 발생하는 이동 효과를 나타냅니다.
픽셀 가로 세로 비율
PAR(픽셀 가로 세로 비율 )은 픽셀의 모양을 측정합니다.
디지털 이미지를 캡처하면 이미지가 세로 및 가로로 샘플링되어 픽셀 또는 골반이라고 하는 정량화된 샘플의 사각형 배열이 생성됩니다. 샘플링 눈금의 모양은 디지털화된 이미지의 픽셀 모양을 결정합니다.
다음은 수학을 단순하게 유지하기 위해 작은 숫자를 사용하는 예제입니다. 원래 이미지가 정사각형이라고 가정합니다(즉, 그림 가로 세로 비율이 1:1). 샘플링 그리드에 4×3 그리드로 정렬된 12개의 요소가 포함되어 있다고 가정합니다. 결과 픽셀의 모양은 너비보다 큽합니다. 특히 각 픽셀의 모양은 3×4입니다. 정사각형이 아닌 픽셀을 제곱이 아닌 픽셀이라고 합니다.
픽셀 가로 세로 비율은 디스플레이 디바이스에도 적용됩니다. 디스플레이 디바이스의 물리적 모양과 물리적 픽셀 해상도(가로 및 아래쪽)는 디스플레이 디바이스의 PAR을 결정합니다. 컴퓨터 모니터는 일반적으로 정사각형 픽셀을 사용합니다. 이미지 PAR 및 디스플레이 PAR이 일치하지 않는 경우 올바르게 표시하려면 이미지를 세로 또는 가로로 한 차원으로 조정해야 합니다. 다음 수식은 PAR, DAR(가로 세로 비율) 및 이미지 크기를 픽셀 단위로 관련합니다.
DAR = (이미지 너비( / 픽셀 이미지 높이 픽셀) × PAR
이 수식의 이미지 너비와 이미지 높이는 표시된 이미지가 아니라 메모리의 이미지를 나타냅니다.
다음은 실제 예제입니다. NTSC-M 아날로그 비디오에는 활성 이미지 영역에 480개의 스캔 라인이 포함되어 있습니다. ITU-R Rec. BT.601은 줄당 704픽셀의 가로 샘플링 속도를 지정하여 704 x 480픽셀의 디지털 이미지를 생성합니다. 의도된 그림 가로 세로 비율은 4:3이며 PAR은 10:11입니다.
- DAR: 4:3
- 너비(픽셀): 704
- 높이(픽셀): 480
- PAR: 10/11
4/3 = (704/480) x(10/11)
이 이미지를 정사각형 픽셀이 있는 디스플레이 디바이스에 올바르게 표시하려면 너비를 10/11로 조정하거나 높이를 11/10으로 조정해야 합니다.
가로 세로 비율 작업
비디오 프레임의 올바른 모양은 PAR(픽셀 가로 세로 비율 ) 및 표시 영역으로 정의됩니다.
- PAR은 이미지에서 픽셀의 모양을 정의합니다. 정사각형 픽셀의 가로 세로 비율은 1:1입니다. 다른 가로 세로 비율은 제곱이 아닌 픽셀을 설명합니다. 예를 들어 NTSC 텔레비전은 10:11 PAR을 사용합니다. 컴퓨터 모니터에 비디오를 표시한다고 가정하면 디스플레이에 정사각형 픽셀(1:1 PAR)이 표시됩니다. 원본 콘텐츠의 PAR은 미디어 형식의 MF_MT_PIXEL_ASPECT_RATIO 특성에 제공됩니다.
- 표시 영역은 표시할 비디오 이미지의 영역입니다. 미디어 유형에 지정할 수 있는 두 가지 관련 표시 영역이 있습니다.
- 이동 및 스캔 조리개입니다. 이동 및 스캔 조리개는 이동/스캔 모드로 표시되어야 하는 비디오의 4×3 영역입니다. 레터박싱 없이 4×3 디스플레이에 와이드 스크린 콘텐츠를 표시하는 데 사용됩니다. 이동 및 스캔 조리개는 MF_MT_PAN_SCAN_APERTURE 특성에 지정되며 MF_MT_PAN_SCAN_ENABLED 특성이 TRUE인 경우에만 사용해야 합니다.
- 조리개를 표시합니다. 이 조리개는 일부 비디오 표준에 정의되어 있습니다. 디스플레이 조리개 외부의 모든 항목은 오버스캔 영역이므로 표시해서는 안 됩니다. 예를 들어 NTSC 텔레비전은 720×480픽셀이며 디스플레이 조리개는 704×480입니다. 표시 조리개는 MF_MT_MINIMUM_DISPLAY_APERTURE 특성에 지정됩니다. 있는 경우 pan-and-scan 모드 가 FALSE일 때 사용해야 합니다.
pan-and-can 모드가 FALSE이고 디스플레이 조리개가 정의되지 않은 경우 전체 비디오 프레임이 표시되어야 합니다. 사실, 이것은 텔레비전 및 DVD 비디오 이외의 대부분의 비디오 콘텐츠에 대 한 경우. 전체 그림의 가로 세로 비율은 PAR를 ×(표시 영역 너비 / 표시 영역 높이)로 계산됩니다.
코드 예제
표시 영역 찾기
다음 코드에서는 미디어 형식에서 표시 영역을 가져오는 방법을 보여 있습니다.
MFVideoArea MakeArea(float x, float y, DWORD width, DWORD height);
HRESULT GetVideoDisplayArea(IMFMediaType *pType, MFVideoArea *pArea)
{
HRESULT hr = S_OK;
BOOL bPanScan = FALSE;
UINT32 width = 0, height = 0;
bPanScan = MFGetAttributeUINT32(pType, MF_MT_PAN_SCAN_ENABLED, FALSE);
// In pan-and-scan mode, try to get the pan-and-scan region.
if (bPanScan)
{
hr = pType->GetBlob(MF_MT_PAN_SCAN_APERTURE, (UINT8*)pArea,
sizeof(MFVideoArea), NULL);
}
// If not in pan-and-scan mode, or the pan-and-scan region is not set,
// get the minimimum display aperture.
if (!bPanScan || hr == MF_E_ATTRIBUTENOTFOUND)
{
hr = pType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)pArea,
sizeof(MFVideoArea), NULL);
if (hr == MF_E_ATTRIBUTENOTFOUND)
{
// Minimum display aperture is not set.
// For backward compatibility with some components,
// check for a geometric aperture.
hr = pType->GetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)pArea,
sizeof(MFVideoArea), NULL);
}
// Default: Use the entire video area.
if (hr == MF_E_ATTRIBUTENOTFOUND)
{
hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height);
if (SUCCEEDED(hr))
{
*pArea = MakeArea(0.0, 0.0, width, height);
}
}
}
return hr;
}
MFOffset MakeOffset(float v)
{
MFOffset offset;
offset.value = short(v);
offset.fract = WORD(65536 * (v-offset.value));
return offset;
}
MFVideoArea MakeArea(float x, float y, DWORD width, DWORD height)
{
MFVideoArea area;
area.OffsetX = MakeOffset(x);
area.OffsetY = MakeOffset(y);
area.Area.cx = width;
area.Area.cy = height;
return area;
}
픽셀 가로 세로 비율 간 변환
다음 코드에서는 그림 가로 세로 비율을 유지하면서 사각형을 PAR(픽셀 가로 세로 비율)에서 다른 픽셀로 변환하는 방법을 보여 줍니다.
//-----------------------------------------------------------------------------
// Converts a rectangle from one pixel aspect ratio (PAR) to another PAR.
// Returns the corrected rectangle.
//
// For example, a 720 x 486 rect with a PAR of 9:10, when converted to 1x1 PAR,
// must be stretched to 720 x 540.
//-----------------------------------------------------------------------------
RECT CorrectAspectRatio(const RECT& src, const MFRatio& srcPAR, const MFRatio& destPAR)
{
// Start with a rectangle the same size as src, but offset to (0,0).
RECT rc = {0, 0, src.right - src.left, src.bottom - src.top};
// If the source and destination have the same PAR, there is nothing to do.
// Otherwise, adjust the image size, in two steps:
// 1. Transform from source PAR to 1:1
// 2. Transform from 1:1 to destination PAR.
if ((srcPAR.Numerator != destPAR.Numerator) ||
(srcPAR.Denominator != destPAR.Denominator))
{
// Correct for the source's PAR.
if (srcPAR.Numerator > srcPAR.Denominator)
{
// The source has "wide" pixels, so stretch the width.
rc.right = MulDiv(rc.right, srcPAR.Numerator, srcPAR.Denominator);
}
else if (srcPAR.Numerator < srcPAR.Denominator)
{
// The source has "tall" pixels, so stretch the height.
rc.bottom = MulDiv(rc.bottom, srcPAR.Denominator, srcPAR.Numerator);
}
// else: PAR is 1:1, which is a no-op.
// Next, correct for the target's PAR. This is the inverse operation of
// the previous.
if (destPAR.Numerator > destPAR.Denominator)
{
// The destination has "wide" pixels, so stretch the height.
rc.bottom = MulDiv(rc.bottom, destPAR.Numerator, destPAR.Denominator);
}
else if (destPAR.Numerator < destPAR.Denominator)
{
// The destination has "tall" pixels, so stretch the width.
rc.right = MulDiv(rc.right, destPAR.Denominator, destPAR.Numerator);
}
// else: PAR is 1:1, which is a no-op.
}
return rc;
}
편지함 영역 계산
다음 코드는 원본 및 대상 사각형이 지정된 레터박스 영역을 계산합니다. 두 사각형의 PAR이 같을 것으로 가정합니다.
RECT LetterBoxRect(const RECT& rcSrc, const RECT& rcDst)
{
// Compute source/destination ratios.
int iSrcWidth = rcSrc.right - rcSrc.left;
int iSrcHeight = rcSrc.bottom - rcSrc.top;
int iDstWidth = rcDst.right - rcDst.left;
int iDstHeight = rcDst.bottom - rcDst.top;
int iDstLBWidth;
int iDstLBHeight;
if (MulDiv(iSrcWidth, iDstHeight, iSrcHeight) <= iDstWidth)
{
// Column letterboxing ("pillar box")
iDstLBWidth = MulDiv(iDstHeight, iSrcWidth, iSrcHeight);
iDstLBHeight = iDstHeight;
}
else
{
// Row letterboxing.
iDstLBWidth = iDstWidth;
iDstLBHeight = MulDiv(iDstWidth, iSrcHeight, iSrcWidth);
}
// Create a centered rectangle within the current destination rect
LONG left = rcDst.left + ((iDstWidth - iDstLBWidth) / 2);
LONG top = rcDst.top + ((iDstHeight - iDstLBHeight) / 2);
RECT rc;
SetRect(&rc, left, top, left + iDstLBWidth, top + iDstLBHeight);
return rc;
}
관련 항목