Processamento de imagens com JavaScript

Processamento de imagens com JavaScript

O processamento do lado do cliente é um aspecto fundamental da construção de sites modernos e aplicativos da web interativos. Por esse motivo, é sabido que tudo o que podemos calcular ou processar primeiro no navegador resulta no desempenho e na apresentação geral do serviço que prestamos com nossos projetos de software.

Às vezes pode ser útil permitir que o usuário pegue algum arquivo de imagem através de nosso aplicativo da web, sem ter que enviá-lo para o servidor (ou atrasar o envio por algum tempo depois) e trabalhar com ele primeiro no lado do cliente.

Isso pode ser motivado por vários motivos, entre outros:

  • Decisões de desempenho, como só preciso de uma miniatura da imagem antes de submit ou ela será enviada depois (ou nunca).
  • Reduza o tamanho ou a qualidade da imagem em questão antes de enviá-la pela rede, para economizar tráfego ou devido à natureza ou modo de funcionamento do meu aplicativo.
  • Queremos melhorar a experiência do usuário e pretendemos usar técnicas de compressão ou redução de tamanho para otimizar o desempenho.
  • Qualquer outro pré-processamento necessário.

Resumindo, permitir que os usuários carreguem e manipulem arquivos de imagem diretamente no navegador é uma maneira eficaz de melhorar o desempenho e a qualidade de nossos aplicativos on-line, aproveitando ao máximo os recursos do navegador e usando técnicas de processamento de imagem.

Quando falamos sobre processamento do lado do cliente, é claro que a abordagem direta é usar JavaScript para realizar essa tarefa. Dada a sua capacidade de atuar no DOM e executar operações em tempo real, é a escolha preferida para isso.

Com esse contexto em mente, apresento este exemplo, escrito puramente em JavaScript e embutido em uma planilha HTML. Mas nem é preciso dizer que é um código que pode ser facilmente usado em um frontend atual ou melhorado com as facilidades fornecidas por uma biblioteca como jQuery. Na verdade, esse método foi usado em um caso de uso real, dividido em algumas etapas ou submétodos em um script Vue.js.

Às vezes, podemos precisar redimensionar ou dimensionar imagens específicas para caber em um tamanho ou formato predeterminado.

Vou levar isso para um exemplo prático: Temos a situação em que queremos trabalhar com imagens de apenas 500x500 px, então precisaremos de um canvas quadrado desse tamanho para que as imagens selecionadas possam ser adaptadas corretamente a ele. Com esta abordagem, podemos garantir que todas as imagens tenham um tamanho uniforme, previamente conhecido e perfeitamente adaptado às nossas condições de trabalho, largura de banda ou ao design que meticulosamente implementamos no nosso frontend.

Em poucas palavras, a sequência e sua explicação são as seguintes:

Temos um arquivo HTML bem simples, dentro do DOM um botão que chama a função que fará a tarefa e um div ao qual por fim iremos anexar o canvas resultante.

Ao clicar no botão, a função getFile é chamada e executada, que será assíncrona.

Agora, dentro da função definimos o objeto arquivo, com o qual permitimos ao usuário escolher um arquivo de imagem usando o seletor do objeto window. Este seletor abre o que conhecemos como caixa de diálogo de seleção de arquivo do nosso sistema operacional, como se fosse um botão de entrada do tipo file.

Definimos uma variável com a foto em questão, a única dentro da lista de arquivos escolhidos (que pode ser mais, dependendo se definimos a seleção múltipla de arquivos ou não). Essas operações devem aguardar sua conclusão para continuar e é por isso que as chamamos com await.

Então, se necessário, pode-se definir a opção multiple para permitir a seleção de vários arquivos de uma só vez, o que exigirá alterações no código, como percorrer todo o array que compõe a lista de arquivos.

Neste ponto vamos definir um leitor para nossa foto, que possui um evento onerror que podemos usar caso algo não saia como o esperado.

Dentro do leitor pegamos os dados da foto e definimos o tamanho máximo para nosso canvas.

Também criamos um elemento de imagem que não exibiremos na tela; simplesmente a usaremos para trabalhar com a imagem selecionada e posteriormente incorporá-la ao canvas previamente definido.

O objeto Image também possui um evento onerror que podemos detectar.

Dentro do evento onload da imagem vamos construir o canvas, lembrando que canvas é uma tela em branco para nosso DOM e que podemos usar em nossos sites, já que é um elemento HTML.

Ele permite desenhar gráficos através de comandos (geralmente JavaScript), fazer composições de fotos ou até mesmo animações.

A melhor decisão seria calcular o tamanho final da imagem e posicioná-la proporcionalmente dentro do canvas. Este caso considera imagens horizontais maiores que a tela, mas pode ser adaptado com muita facilidade. Usamos uma regra simples, para calcular a taxa de redução de tamanho (aqui, para a altura da imagem) e depois um cálculo de sua posição final de acordo com o tamanho do canvas.

Em seguida, desenhamos a imagem no canvas e anexe a tela ao div do nosso DOM para renderizar na tela usando append.

Agora sim, estamos prontos e podemos querer enviar o canvas resultante para o servidor (ou pelo menos disponibilizá-lo para ele), então devemos passá-lo para uma imagem. Para fazer isso, converteremos a tela em um blob, ou seja, um grande objeto binário.


O blob de tela pode então ser enviado para um endpoint de backend preciso que recebe essa nova imagem (em sua nova forma e tamanho) e a converte em um arquivo adequadamente ou executa algum outro processamento (como análise ou reconhecimento de IA).

Aqui, anexei um captura de tela do resultado e código completo, com alguns comentários:

Pronto! Agora você já sabe como processar imagens com JavaScript de forma simples e eficaz.

Todo o sucesso em seus projetos futuros.

Saudações!

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.