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

Publicado por Mauricio Ferrari em 01/02/2023

[ Hits: 2.436 ]

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

Executando um Comando ou Programa como Outro Usuário

Extraindo Dados de Sites da Internet pelo Terminal

Leafpad no Linux Mint 20

Avidemux não abre no Salix 14.2 [Resolvido]

Três Formas Fáceis de usar Super Usuário pelo Terminal no Linux

Leitura recomendada

printf("Criando Delay em Linguagem C de forma SIMPLES");

C compiler Cannot create executable?

Baixe de graça alguns livros do O'Reilly

Programando em C/C++ no Eclipse

Ambiente de desenvolvimento integrado para console

  

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