Efetuando cálculo de Aspect Ratio de vídeos em C/C++

Publicado por Mauricio Ferrari em 01/02/2023

[ Hits: 2.009 ]

Blog: https://www.youtube.com/@LinuxDicasPro

 


Efetuando cálculo de Aspect Ratio de vídeos em C/C++



O Aspect Ratio de um vídeo ou imagem é basicamente a proporção entre a largura e a altura do arquivo de mídia, podendo ser expressado com dois números separados com dois pontos como 16:9 por exemplo, e também através do resultado da divisão entre a largura e a altura que no caso 16:9 seria 1.77778 aproximadamente.

Eu estava precisando das informações de Aspect Ratio para o exibir nas informações de mídia do meu projeto. Mas, o que o libmediainfo me entregava era só o resultado da divisão entre a largura e a altura, o tal do 1.778 no caso da biblioteca que eu estava usando.

Procurando na internet, eu achei um site que eu consegui salvar e extrair a uma função em JavaScript que efetuava o cálculo que eu queria. A função era basicamente isso:

// Calculate the Aspect Ratios of given values
function get_aspectRatio(){

    var resTd = document.getElementById("msg_status");
        resTd.innerHTML = '';

    if( (!document.getElementById('aspect_width').value.isNumber()) || (!document.getElementById('aspect_height').value.isNumber()) ){

        resTd.innerHTML =
            " <div class='alert alert-warning fade in' role='alert'> Invalid width or height entered </div>";
        return;
    }

    var w=parseInt(document.getElementById('aspect_width').value);
    var h=parseInt(document.getElementById('aspect_height').value);

    if(h == 0 && w == 0){

        resTd.innerHTML =
            " <div class='alert alert-warning fade in' role='alert'> Please enter valid width and height values! </div>";
        return;
    }
    if(h == 0 && w != 0){

        resTd.innerHTML =
            " <div class='alert alert-warning fade in' role='alert'> Please enter a valid height value! </div>";
        return;
    }
    if(h!= 0 && w == 0){

        resTd.innerHTML =
            " <div class='alert alert-warning fade in' role='alert'> Please enter width </div>";
        return;
    }

    if(h == w){
        aspectRatio = '1 : 1';
    }else{
        var mode = null;
        if(h>w)
        {
            dividend  = h;
            divisor   = w;
            mode      ='portrait';
        }

        if(w>h){
            dividend   = w;
            divisor    = h;
            mode       = 'landscape';
        }

        var gcd = -1;
        while(gcd == -1){
            remainder = dividend%divisor;
            if(remainder == 0){
                gcd = divisor;
            }else{
                dividend  = divisor;
                divisor   = remainder;
            }
        }

        var hr         = w/gcd;
        var vr         = h/gcd;
        aspectRatio    = (hr + ' : ' + vr);

    }

    $('.screen_mode').text(mode);
    $('.final_aspect_ratio').text( aspectRatio );
    $('.final_width').text(w);
    $('.final_height').text(h);
    $('.final_dimensions').text(w + ' × ' + h);
}

Com esse achado, eu consegui o resultado que eu queria. Basicamente, o que eu queria era uma função que me retornasse algo assim: "16:9 (Landscape 1.77778)".

Então, só precisei recriar a função para que se adaptasse ao meu projeto:

QString StatisticsWorker::convertAspectRatio(int x, int y) {
    int w = x;
    int h = y;
    int dividend, divisor;

    // Aqui, é definido se o arquivo multimídia é orientado em retrato ou paisagem.
    // Se a largura(w) é igual a altura(h) o Aspect Ratio é 1:1 e dispensa detalhes. 
    if (h == w) {
        return "1:1";
    } else {
        QString mode{};
        if (h > w) {
            // Orientação em retrato: altura/largura
            dividend = h;
            divisor = w;
            mode = "Portrait";
        } else if (w > h) {
            // Orientação em paisagem: largura/altura 
            dividend = w;
            divisor = h;
            mode = "Landscape";
        }

        // A string ratio é definida com a orientação definida incluindo o resultado da divisão entre a largura e a altura ou vice-versa.
        QString ratio{mode + " " + QString::number(((float)dividend / (float)divisor))};

        // Aqui é que vem a calcular. gcd é definido como -1, que será definido um novo valor no loop quando remainder = 0.
        uint gcd = -1;
        int remainder;
        while (gcd == -1) {
            // remainder será o valor da sobra da operação.
            remainder = dividend % divisor;
            if (remainder == 0) {
                // gcd será o divisor perfeito para a largura e a altura.
                gcd = divisor;
            } else {
                // A próxima operação sempre será o resultado do divisor pela sobra.
                dividend = divisor;
                divisor = remainder;
            }
        }

        QString hr = QString::number(w / gcd);
        QString vr = QString::number(h / gcd);
        return QString::fromLatin1("%1 (%2)").arg(hr + ":" + vr, ratio);
    }
}

Colocando isso na ponta da caneta, um cálculo usando uma resolução de 1920x1080 seria:

1920 % 1080 = 840
1080 % 840 = 240
840 % 240 = 120
240 % 120 = 0 (120 é o que procuramos)

1920 / 120 = 16
1080 / 120 = 9

O Aspect Ratio de 1920x1080 é 16:9. E assim, se alguém precisar calcular o Aspect Ratio de algum arquivo de vídeo ou imagem, essa é a fórmula.

Outras dicas deste autor

Listando Serviços e Pacotes mais Facilmente no Slackware

Gambiarra para Atualizar o Menu de Aplicativos no KDE

Incluindo o libmediainfo corretamente em um arquivo CMakeFiles.txt para uso em seus projetos

Função para Abrir uma Interface do tkinter no Centro da Tela em Python

Usando Vídeo Wallpaper no KDE

Leitura recomendada

Usando "sscanf" para Dividir String com Delimitadores em C

Como escrever código portável

C compiler Cannot create executable?

Baixe de graça alguns livros do O'Reilly

STDPRN para GCC

  

Comentários
[1] Comentário enviado por SamL em 01/02/2023 - 13:39h

Gostei! Bem simples.


https://nerdki.blogspot.com/ acessa ai, é grátis
Não gostou? O ícone da casinha é serventia do site!

[2] Comentário enviado por maurixnovatrento em 01/02/2023 - 21:15h


[1] Comentário enviado por SamL em 01/02/2023 - 13:39h

Gostei! Bem simples.


https://nerdki.blogspot.com/ acessa ai, é grátis
Não gostou? O ícone da casinha é serventia do site!


valeu.



Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts