Поделиться через


Пропорции рисунка

В этом разделе описаны два связанных понятия, соотношение аспектов рисунка и пропорции пикселей. Затем описывается, как эти понятия выражаются в Microsoft Media Foundation с помощью типов мультимедиа.

Пропорции рисунка

Пропорции рисунка определяют форму отображаемого изображения видео. Пропорции изображения не учитываются X:Y, где X:Y — это соотношение ширины рисунка к высоте рисунка. Большинство стандартов видео используют пропорции изображения 4:3 или 16:9. Пропорции 16:9 обычно называются широкоэкранным. Фильм кино часто использует пропорции 1:85:1 или 1:66:1. Пропорции рисунка также называются пропорциями отображения (DAR).

diagram showing 4:3 and 16:9 aspect ratios

Иногда изображение видео не имеет той же фигуры, что и область отображения. Например, видео 4:3 может отображаться на широкоэкранном телевидении (16×9). На компьютере видео видео может отображаться в окне с произвольным размером. В этом случае существует три способа размещения изображения в области отображения:

  • Растяните изображение вдоль одной оси, чтобы поместить область отображения.
  • Масштабируйте изображение, чтобы соответствовать области отображения, сохраняя исходное соотношение пропорций изображения.
  • Обрезка изображения.

Растяжение изображения в соответствии с областью отображения почти всегда неправильно, так как оно не сохраняет правильное соотношение пропорций рисунка.

Почтовые ящики

Процесс масштабирования широкоэкранного изображения в соответствии с отображением 4:3 называется почтовым ящиком, показанным на следующей схеме. Результированные прямоугольные области в верхней и нижней части изображения обычно заполнены черным цветом, хотя другие цвета можно использовать.

diagram showing the correct way to letterbox

Обратный регистр, масштабирование изображения 4:3 для размещения широкоэкранного дисплея, иногда называется столпboxing. Однако буквенное поле терминов также используется в общем смысле, чтобы означать масштабирование изображения видео для соответствия любой заданной области отображения.

diagram showing pillarboxing

Сдвига и сканирование

Пан-и-сканирование — это метод, в котором широкоэкранное изображение обрезается до прямоугольной области 4×3 для отображения на устройстве с дисплеем 4:3. Полученное изображение заполняет весь экран, не требуя областей черной буквы, но части исходного изображения обрезаются из рисунка. Область, которая обрезается, может перемещаться из кадра в кадр, так как область интереса сдвигается. Термин "pan" в области сдвига и сканирования относится к эффекту сдвига, которое вызвано перемещением области сдвига и сканирования.

diagram showing pan-and-scan

Пропорции пикселей

Пропорции пикселей (PAR) измеряет форму пикселя.

При захвате цифрового изображения образ выполняется как по вертикали, так и по горизонтали, что приводит к прямоугольным массиву квантизованных выборок, вызываемого пикселями или pels. Форма сетки выборки определяет форму пикселей в цифровом изображении.

Ниже приведен пример, использующий небольшие числа для простоты математических вычислений. Предположим, что исходное изображение равно квадрату (т. е. пропорции рисунка равно 1:1); и предположим, что сетка выборки содержит 12 элементов, упорядоченных в сетке 4×3. Фигура каждого полученного пикселя будет выше, чем она широка. В частности, форма каждого пикселя будет составлять 3×4. Пиксели, которые не являются квадратными, называются некверными пикселями.

diagram showing a non-square sampling grid

Пропорции пикселей также применяются к устройству отображения. Физическая форма устройства отображения и разрешение физических пикселей (по всему и внизу) определяют PAR устройства дисплея. Мониторы компьютера обычно используют квадратные пиксели. Если изображение PAR и экранный par не совпадают, изображение должно масштабироваться в одном измерении (вертикально или горизонтально) для правильного отображения. Следующая формула относится к PAR, пропорции отображения (DAR) и размер изображения в пикселях:

DAR = (ширина изображения в пикселях высоты изображения в пикселях / ) × PAR

Обратите внимание, что ширина изображения и высота изображения в этой формуле ссылаются на изображение в памяти, а не отображаемое изображение.

Ниже приведен пример реального мира: аналоговое видео NTSC-M содержит 480 строк сканирования в активной области изображения. ITU-R Rec. BT.601 указывает горизонтальную частоту выборки 704 видимых пикселей на линию, что дает цифровое изображение с 704 x 480 пикселей. Предполагаемое соотношение пропорций рисунка равно 4:3, что дает значение PAR 10:11.

  • ДАР: 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.
    • Отображение диафрагмы. Эта диафрагма определена в некоторых стандартах видео. Все, что находится за пределами диафрагмы отображения, является областью overscan и не должно отображаться. Например, телевизор NTSC составляет 720×480 пикселей с диафрагмой дисплея 704×480. Диафрагма отображения представлена в атрибуте MF_MT_MINIMUM_DISPLAY_APERTURE . Если он присутствует, его следует использовать, если режим сдвига и сканирования имеет значение FALSE.

Если режим сдвига и может иметь значение 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;
}

Типы носителей

Типы мультимедиа видео

MF_MT_MINIMUM_DISPLAY_APERTURE

MF_MT_PAN_SCAN_APERTURE

MF_MT_PAN_SCAN_ENABLED

MF_MT_PIXEL_ASPECT_RATIO