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

Publicado por Mauricio Ferrari em 01/02/2023

[ Hits: 1.932 ]

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

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

Google Chrome no SliTaz 5.0

Instalando a última versão do LibreOffice no Linux Mint e Ubuntu

O Mais Prático ou o Mais Rápido? Alternativa ao cut -c

Instalando o IPTVnator no Slackware

Leitura recomendada

GDB "hackeando" programas

Como escrever código portável

Autoestudo e certificação C/C++

Como criar bibliotecas dinâmicas em C/C++

Corrigindo o bug "file format not recognized" após atualizar glib2

  

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