Rasio Aspek Gambar

Topik ini menjelaskan dua konsep terkait, rasio aspek gambar dan rasio aspek piksel. Kemudian menjelaskan bagaimana konsep ini diekspresikan di Microsoft Media Foundation menggunakan jenis media.

Rasio Aspek Gambar

Rasio aspek gambar menentukan bentuk gambar video yang ditampilkan. Rasio aspek gambar diberitahukan X:Y, di mana X:Y adalah rasio lebar gambar terhadap tinggi gambar. Sebagian besar standar video menggunakan rasio aspek gambar 4:3 atau 16:9. Rasio aspek 16:9 umumnya disebut layar lebar. Film bioskop sering menggunakan rasio aspek 1:85:1 atau 1:66:1. Rasio aspek gambar juga disebut rasio aspek tampilan (DAR).

diagram showing 4:3 and 16:9 aspect ratios

Terkadang gambar video tidak memiliki bentuk yang sama dengan area tampilan. Misalnya, video 4:3 mungkin ditampilkan di televisi layar lebar (16×9). Dalam video komputer, video mungkin ditampilkan di dalam jendela yang memiliki ukuran arbitrer. Dalam hal ini, ada tiga cara gambar dapat dibuat agar pas di dalam area tampilan:

  • Regangkan gambar di sepanjang satu sumbu agar pas dengan area tampilan.
  • Skalakan gambar agar sesuai dengan area tampilan, sambil mempertahankan rasio aspek gambar asli.
  • Potong gambar.

Membentangkan gambar agar pas dengan area tampilan hampir selalu salah, karena tidak mempertahankan rasio aspek gambar yang benar.

Kotak Surat

Proses penskalaan gambar layar lebar agar pas dengan tampilan 4:3 disebut kotak surat, yang ditunjukkan pada diagram berikutnya. Area persegi panjang yang dihasilkan di bagian atas dan bawah gambar biasanya diisi dengan hitam, meskipun warna lain dapat digunakan.

diagram showing the correct way to letterbox

Kasus terbalik, menskalakan gambar 4:3 agar pas dengan layar lebar, terkadang disebut pillarboxing. Namun, kotak surat istilah juga digunakan dalam arti umum, untuk berarti menskalakan gambar video agar sesuai dengan area tampilan tertentu.

diagram showing pillarboxing

Pan-and-Scan

Pan-and-scan adalah teknik di mana gambar layar lebar dipangkas ke area persegi panjang 4×3, untuk ditampilkan pada perangkat tampilan 4:3. Gambar yang dihasilkan mengisi seluruh tampilan, tanpa memerlukan area kotak surat hitam, tetapi bagian dari gambar asli dipotong dari gambar. Area yang dipangkas dapat berpindah dari bingkai ke bingkai, saat area minat bergeser. Istilah "pan" dalam pan-and-scan mengacu pada efek panning yang disebabkan oleh pemindahan area pan-and-scan.

diagram showing pan-and-scan

Rasio Aspek Piksel

Rasio aspek piksel (PAR) mengukur bentuk piksel.

Saat gambar digital diambil, gambar diambil sampelnya baik secara vertikal maupun horizontal, menghasilkan array persegi panjang sampel berukuran, yang disebut piksel atau pel. Bentuk kisi pengambilan sampel menentukan bentuk piksel dalam gambar digital.

Berikut adalah contoh yang menggunakan angka kecil untuk menjaga matematika tetap sederhana. Misalkan gambar asli adalah persegi (yaitu, rasio aspek gambar adalah 1:1); dan misalkan kisi pengambilan sampel berisi 12 elemen, disusun dalam kisi 4×3. Bentuk setiap piksel yang dihasilkan akan lebih tinggi dari lebarnya. Secara khusus, bentuk setiap piksel akan menjadi 3×4. Piksel yang bukan persegi disebut piksel non-persegi.

diagram showing a non-square sampling grid

Rasio aspek piksel juga berlaku untuk perangkat tampilan. Bentuk fisik perangkat tampilan dan resolusi piksel fisik (di seluruh dan ke bawah) menentukan PAR perangkat tampilan. Monitor komputer umumnya menggunakan piksel persegi. Jika PAR gambar dan PAR tampilan tidak cocok, gambar harus diskalakan dalam satu dimensi, baik secara vertikal atau horizontal, agar dapat ditampilkan dengan benar. Rumus berikut berkaitan dengan PAR, rasio aspek tampilan (DAR), dan ukuran gambar dalam piksel:

DAR = (lebar gambar dalam tinggi gambar piksel / dalam piksel) × PAR

Perhatikan bahwa lebar gambar dan tinggi gambar dalam rumus ini merujuk ke gambar dalam memori, bukan gambar yang ditampilkan.

Berikut adalah contoh dunia nyata: Video analog NTSC-M berisi 480 baris pemindaian di area gambar aktif. ITU-R Rec. BT.601 menentukan laju pengambilan sampel horizontal 704 piksel yang terlihat per baris, menghasilkan gambar digital dengan 704 x 480 piksel. Rasio aspek gambar yang dimaksudkan adalah 4:3, menghasilkan PAR 10:11.

  • Dar: 4:3
  • Lebar dalam piksel: 704
  • Tinggi dalam piksel: 480
  • PAR: 10/11

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

Untuk menampilkan gambar ini dengan benar pada perangkat tampilan dengan piksel persegi, Anda harus menskalakan lebar sebesar 10/11 atau tinggi 11/10.

Bekerja dengan Rasio Aspek

Bentuk bingkai video yang benar ditentukan oleh rasio aspek piksel (PAR) dan area tampilan.

  • PAR menentukan bentuk piksel dalam gambar. Piksel persegi memiliki rasio aspek 1:1. Rasio aspek lainnya menjelaskan piksel non-persegi. Misalnya, televisi NTSC menggunakan PAR 10:11. Dengan asumsi bahwa Anda menyajikan video di monitor komputer, layar akan memiliki piksel persegi (1:1 PAR). PAR konten sumber diberikan dalam atribut MF_MT_PIXEL_ASPECT_RATIO pada jenis media.
  • Area tampilan adalah wilayah gambar video yang dimaksudkan untuk ditampilkan. Ada dua area tampilan relevan yang mungkin ditentukan dalam jenis media:
    • Bukaan pan-dan-scan. Bukaan pan-and-scan adalah wilayah video 4×3 yang harus ditampilkan dalam mode pan/scan. Ini digunakan untuk menampilkan konten layar lebar pada tampilan 4×3 tanpa kotak surat. Aperture pan-and-scan diberikan dalam atribut MF_MT_PAN_SCAN_APERTURE dan harus digunakan hanya ketika atribut MF_MT_PAN_SCAN_ENABLED TRUE.
    • Tampilkan bukaan. Aperture ini didefinisikan dalam beberapa standar video. Apa pun di luar bukaan tampilan adalah wilayah overscan dan tidak boleh ditampilkan. Misalnya, televisi NTSC adalah 720×480 piksel dengan bukaan layar 704×480. Aperture tampilan diberikan dalam atribut MF_MT_MINIMUM_DISPLAY_APERTURE. Jika ada, ini harus digunakan saat mode pan-and-scan adalah FALSE.

Jika mode pan-and-can FALSE dan tidak ada bukaan tampilan yang ditentukan, seluruh bingkai video harus ditampilkan. Bahkan, ini adalah kasus untuk sebagian besar konten video selain televisi dan video DVD. Rasio aspek seluruh gambar dihitung sebagai (tinggi area tampilan lebar / tampilan tampilan) × PAR.

Contoh Kode

Menemukan Area Tampilan

Kode berikut menunjukkan cara mendapatkan area tampilan dari jenis media.

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

Mengonversi Antara Rasio Aspek Piksel

Kode berikut menunjukkan cara mengonversi persegi panjang dari satu rasio aspek piksel (PAR) ke yang lain, sambil mempertahankan rasio aspek gambar.

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

Menghitung Area Kotak Surat

Kode berikut menghitung area kotak surat, dengan sumber dan persegi panjang tujuan. Diasumsikan bahwa kedua persegi panjang memiliki PAR yang sama.

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

Jenis Media

Tipe Media Video

MF_MT_MINIMUM_DISPLAY_APERTURE

MF_MT_PAN_SCAN_APERTURE

MF_MT_PAN_SCAN_ENABLED

MF_MT_PIXEL_ASPECT_RATIO