Relación de aspecto de imagen

En este tema se describen dos conceptos relacionados, relación de aspecto de imagen y relación de aspecto de píxeles. A continuación, se describe cómo se expresan estos conceptos en Microsoft Media Foundation mediante tipos de medios.

Relación de aspecto de imagen

La relación de aspecto de imagen define la forma de la imagen de vídeo mostrada. La relación de aspecto de la imagen se nota X:Y, donde X:Y es la relación del ancho de la imagen con el alto de la imagen. La mayoría de los estándares de vídeo usan la relación de aspecto de imagen 4:3 o 16:9. La relación de aspecto 16:9 se llamada normalmente widescreen. La película cinematográfica suele usar una relación de aspecto 1:85:1 o 1:66:1. La relación de aspecto de la imagen también se denomina relación de aspecto de pantalla (DAR).

diagram showing 4:3 and 16:9 aspect ratios

A veces, la imagen de vídeo no tiene la misma forma que el área de visualización. Por ejemplo, un vídeo 4:3 podría mostrarse en un televisor de pantalla ancha (16×9). En el vídeo del equipo, es posible que el vídeo se muestre dentro de una ventana que tenga un tamaño arbitrario. En ese caso, hay tres maneras de que la imagen se pueda ajustar dentro del área de visualización:

  • Ampliar la imagen a lo largo de un eje para ajustarse al área de visualización.
  • Escale la imagen para ajustarse al área de visualización, a la vez que mantiene la relación de aspecto de la imagen original.
  • Recorte la imagen.

Ampliar la imagen para ajustarla al área de presentación es casi siempre un error, porque no conserva la relación de aspecto correcta de la imagen.

Letterboxing

El proceso de escalado de una imagen de pantalla ancha para ajustarse a una pantalla 4:3 se denomina letterboxing, que se muestra en el diagrama siguiente. Las áreas rectangulares resultantes en la parte superior e inferior de la imagen suelen rellenarse con negro, aunque se pueden usar otros colores.

diagram showing the correct way to letterbox

El caso inverso, escalando una imagen de 4:3 para ajustarse a una pantalla ancha, a veces se denomina pillarboxing. Sin embargo, el término letterbox también se usa en un sentido general, para significar el escalado de una imagen de vídeo para ajustarse a cualquier área de visualización determinada.

diagram showing pillarboxing

Movimiento panorámico y examen

Panorámica y examen es una técnica por la que una imagen de pantalla ancha se recorta en un área rectangular de 4×3, para su visualización en un dispositivo de pantalla 4:3. La imagen resultante rellena toda la pantalla, sin necesidad de áreas de bandeja de letras negras, pero las partes de la imagen original se recortan fuera de la imagen. El área recortada puede pasar de marco a marco, ya que el área de interés cambia. El término "panorámica" en exploración panorámica hace referencia al efecto de movimiento panorámico causado por el movimiento panorámico del área de movimiento panorámico y examen.

diagram showing pan-and-scan

Relación de aspecto de píxeles

La relación de aspecto de píxeles (PAR) mide la forma de un píxel.

Cuando se captura una imagen digital, la imagen se muestrea tanto vertical como horizontalmente, lo que da lugar a una matriz rectangular de muestras cuantificadas, denominadas píxeles o elemento de imagen. La forma de la cuadrícula de muestreo determina la forma de los píxeles de la imagen digitalizada.

Este es un ejemplo que usa números pequeños para simplificar las matemáticas. Supongamos que la imagen original es cuadrada (es decir, la relación de aspecto de la imagen es 1:1); y supongamos que la cuadrícula de muestreo contiene 12 elementos, organizados en una cuadrícula 4×3. La forma de cada píxel resultante será más alta de lo que es ancho. En concreto, la forma de cada píxel será 3×4. Los píxeles que no son cuadrados se denominan píxeles no cuadrados.

diagram showing a non-square sampling grid

La relación de aspecto de píxeles también se aplica al dispositivo de visualización. La forma física del dispositivo de visualización y la resolución de píxeles físicos (entre y abajo) determinan el PAR del dispositivo de visualización. Los monitores de equipo suelen usar píxeles cuadrados. Si la imagen PAR y el PAR para mostrar no coinciden, la imagen debe escalarse en una dimensión, ya sea vertical o horizontalmente, para que se muestre correctamente. La fórmula siguiente relaciona PAR, relación de aspecto de visualización (DAR) y tamaño de imagen en píxeles:

DAR = (ancho de imagen en píxeles / alto de imagen en píxeles) × PAR

Tenga en cuenta que el ancho de la imagen y el alto de la imagen en esta fórmula hacen referencia a la imagen en memoria, no a la imagen mostrada.

Este es un ejemplo real: el vídeo analógico NTSC-M contiene 480 líneas de examen en el área de imagen activa. UIT-R Rec. BT.601 especifica una frecuencia de muestreo horizontal de 704 píxeles visibles por línea, lo que produce una imagen digital con 704 x 480 píxeles. La relación de aspecto de imagen prevista es 4:3, lo que produce un PAR de 10:11.

  • DAR: 4:3
  • Ancho en píxeles: 704
  • Alto en píxeles: 480
  • PAR: 10/11

4/3 = (704/480) x (10/11)

Para mostrar esta imagen correctamente en un dispositivo de visualización con píxeles cuadrados, debe escalar el ancho en 10/11 o el alto en 11/10.

Trabajar con relaciones de aspecto

La forma correcta de un fotograma de vídeo se define mediante la relación de aspecto de píxel (PAR) y el área de visualización.

  • Par define la forma de los píxeles de una imagen. Los píxeles cuadrados tienen una relación de aspecto de 1:1. Cualquier otra relación de aspecto describe un píxel no cuadrado. Por ejemplo, el televisor NTSC usa un PAR 10:11. Suponiendo que está presentando el vídeo en un monitor de equipo, la pantalla tendrá píxeles cuadrados (1:1 PAR). El PAR del contenido de origen se da en el atributo MF_MT_PIXEL_ASPECT_RATIO en el tipo de medio.
  • El área de visualización es la región de la imagen de vídeo que está pensada para mostrarse. Hay dos áreas de visualización pertinentes que podrían especificarse en el tipo de medio:
    • Movimiento panorámico y digitalización. La apertura de panorámica y examen es una región de 4×3 de vídeo que se debe mostrar en modo de panorámica/examen. Se usa para mostrar contenido de pantalla ancha en una pantalla de 4×3 sin bandeja de letras. La apertura de panorámica y examen se da en el atributo MF_MT_PAN_SCAN_APERTURE y solo se debe usar cuando el atributo MF_MT_PAN_SCAN_ENABLED es TRUE.
    • Apertura de pantalla. Esta apertura se define en algunos estándares de vídeo. Todo lo que quede fuera de la apertura de la pantalla es la región de sobreescaneado y no debe mostrarse. Por ejemplo, el televisor NTSC es de 720×480 píxeles con una abertura de pantalla de 704×480. La apertura de la pantalla se da en el atributo MF_MT_MINIMUM_DISPLAY_APERTURE. Si está presente, se debe usar cuando el modo de movimiento panorámico y examen es FALSE.

Si el modo de movimiento panorámico y puede ser FALSE y no se define ninguna apertura de pantalla, se debe mostrar todo el fotograma de vídeo. De hecho, este es el caso de la mayoría de los contenidos de vídeo que no sean televisión y vídeo de DVD. La relación de aspecto de toda la imagen se calcula como (ancho de área / de visualización)× PAR.

Ejemplos de código

Buscar el área de visualización

En el código siguiente se muestra cómo obtener el área de visualización del tipo de medio.

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;
}

Conversión entre relaciones de aspecto de píxeles

En el código siguiente se muestra cómo convertir un rectángulo de una relación de aspecto de píxeles (PAR) a otra, a la vez que se conserva la relación de aspecto de la imagen.

//-----------------------------------------------------------------------------
// 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;
}

Calcular el área de la bandeja de letras

El código siguiente calcula el área del cuadro de letras, dado un rectángulo de origen y de destino. Se supone que ambos rectángulos tienen el mismo 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;
}

Tipos de medios

Tipos de medios de vídeo

MF_MT_MINIMUM_DISPLAY_APERTURE

MF_MT_PAN_SCAN_APERTURE

MF_MT_PAN_SCAN_ENABLED

MF_MT_PIXEL_ASPECT_RATIO