Atualmente, estou trabalhando em um pequeno projeto paralelo, no qual carrego imagens no meu servidor (usando entrada de arquivo e adicionalmente o destino de compartilhamento na Web) para disponibilizá-las a outras pessoas. Enquanto eu tinha a primeira versão de trabalho pronta rapidamente, havia um problema: ao enviar uma imagem em retrato do meu telefone, a imagem era mostrada com a orientação errada.
Neste artigo, você aprenderá sobre o status atual da orientação de imagem na Web, como corrigir a orientação de imagens usando o Node.js. e como os navegadores lidarão com isso no futuro.
Status atual #
Se você visualizar esta imagem (obtida nos exemplos de orientação exif ), ela pode ser exibida corretamente no modo retrato ou pode ser mostrada incorretamente 90 graus, girada para a esquerda.
Você provavelmente é um navegador no iOS se vir a palavra top na verdade na parte superior e outro navegador se vir a palavra top à esquerda. A razão para isso é que os dados EXIF para esta imagem têm as informações Girar 90 CW para orientação.
Quando você incorpora a imagem usando <img>
, ou background-image
a imagem será mostrada incorreta em todos os navegadores, exceto nos navegadores no iOS. No entanto, se você abrir a imagem diretamente, ela será exibida corretamente no Firefox, Chrome e Safari, mas ainda será mostrada incorretamente girada no Edge e no Internet Explorer. Que grande consistência!
A propriedade de orientação da imagem #
Ao procurar maneiras possíveis de corrigir a orientação usando CSS ou JavaScript, descobri a propriedade de orientação da imagem .
No momento, essa propriedade é suportada apenas no Firefox e você pode usá-la desta maneira para que os navegadores respeitem os dados EXIF e corrijam a orientação:
img { image-orientation: from-image;}
Ao procurar mais informações, também descobri que essa propriedade já está obsoleta, o que foi confuso para mim no início, porque essa propriedade seria uma maneira fácil de corrigir meu problema com a orientação da imagem, se ela fosse suportada por todos os navegadores.
Depois de ler um pouco mais sobre a questão do Github, aprendi que o plano é que todos os navegadores respeitem a orientação EXIF no futuro e, portanto, usem image-orientation: from-image
por padrão. Ótimo, é isso que eu quero!
Corrigindo a orientação com Node.js #
Aprendemos até agora que há bastante desacordo entre os navegadores sobre como lidar com a orientação EXIF e nenhuma maneira entre navegadores para corrigi-la facilmente no front-end. Resumindo, é uma bagunça e, como não queremos que alguns usuários vejam imagens quebradas , vamos ver como podemos corrigir isso usando o Node.js.
Primeiro, precisamos de um formulário para fazer upload de nossas imagens:
<form class="form" action="./upload" enctype="multipart/form-data" method="POST"> <label for="file">Select image: </label> <input type="file" required name="file" multiple="" accept="image/*"> <input type="submit" value="Upload your photos"></form>
Depois de selecionar uma imagem e enviar o formulário, uma solicitação POST será feita para / upload, então vamos ver a rota de upload a seguir:
app.post('/upload', upload.array('file'), async(req, res, next) => { const images = req.files; for (image of images) { await correctOrientation(image); } res.redirect('./show');});
Estamos usando a multer como um middleware aqui para processar as imagens e para cada imagem que chamamos correctOrientation
para corrigir a orientação.
Antes de analisarmos correctOrientation
, aqui está a configuração de multer que estamos usando para salvar imagens em nossa pasta / uploads.
var storage = multer.diskStorage({ destination: function(req, file, cb) { cb(null, path.join(__dirname, "uploads")); }, filename: function(req, file, cb) { cb(null, Date.now() + '__' + file.originalname); }})const upload = multer({ storage: storage });
Então, vamos ver a parte interessante – a correção da orientação da imagem:
const readFileAsync = async(file) => { return await new Promise((resolve, reject) => { fs.readFile(file, async(err, data) => { err ? reject(err) : resolve(data); }); });};const correctOrientation = async(image) => { let imageOrientation = false; let rotateDeg = 0; const buffer = modifyExif(await readFileAsync(path.join(__dirname, "uploads") + '/' + image.filename), data => { imageOrientation = data && data["0th"] && data["0th"]["274"] ? data["0th"]["274"] : false; if (imageOrientation) { if (imageOrientation === 1) { imageOrientation = false; } else { data["0th"]["274"] = 1; // reset EXIF orientation value } } }); if (imageOrientation) { switch (imageOrientation) { case 3: rotateDeg = 180; break; case 6: rotateDeg = 270; break; case 8: rotateDeg = 90; reak; default: rotateDeg = 0; break; } Jimp.read(buffer, (err, lenna) => { if (err) { console.log('err', err); return; } lenna .rotate(rotateDeg) // correct orientation .write(path.join(__dirname, "uploads") + '/' + image.filename); // save }); }};
Primeiro, definimos o readFileAsync
que transforma a função fs.readFile em uma promessa.
Agora, vamos ver o que temos na função real. Primeiro, estamos usando o pacote modify-exif para definir o valor da orientação EXIF para cada imagem com o valor 1 (o padrão) se já não fosse 1 .
Depois de alterar as informações EXIF, agora usamos o jimp para girar a imagem de acordo com o valor de orientação EXIF obtido anteriormente e salve a imagem novamente.
E é isso – todas as imagens agora são mostradas corretamente em todos os navegadores.
Você pode encontrar o exemplo completo no Github.
Conclusão #
A partir de agora, o único navegador que respeita a orientação EXIF são os navegadores no iOS, mas há esperança de que todos os outros navegadores, mais cedo ou mais tarde, também os honrem e mostrem a orientação correta. Dessa forma, esse problema seria resolvido automaticamente e nós, desenvolvedores, temos um problema a menos para lidar.
No entanto, no momento, a única maneira de corrigir o problema de orientação é removendo os dados de orientação EXIF e girando a imagem adequadamente, o que pode ser feito manualmente ou usando seu backend favorito. Também seria possível corrigi-lo no lado do cliente usando JavaScript, mas eu desaconselho, pois devemos terceirizar o menos possível o trabalho pesado para o front-end e, portanto, para o usuário.
Codificação feliz e não se esqueça de informar ao seu navegador favorito que eles devem respeitar a orientação EXIF e corrigir esse problema.