Estou desenvolvendo um aplicativo da web em Node.js (+ express 4) onde os usuários podem definir sua imagem de perfil enviando-a para o servidor. Já limitamos o tipo MIME do arquivo e o tamanho máximo do arquivo, de modo que o usuário não pode enviar mais de 200 KB de imagens png ou JPEG.
O problema é que gostaríamos de redimensionar (lado do servidor) a resolução da imagem enviada para 200x200 para melhorar o carregamento da página e economizar espaço no disco. Depois de alguma pesquisa, todas as respostas apontaram para o uso de qualquer módulo baseado em ImageMagick ou GraphicsMagick.
No entanto, ter que instalar o ImageMagick / GraphicsMagick para fazer um redimensionamento simples da imagem parece um exagero para mim, então, existe alguma outra solução além desta para Node.js?
Edit: Eu mudei a solução aceita para nítida porque a solução anterior (lwip) não é mais mantida. Obrigado por todos os seus comentários!
fonte
Respostas:
Eu votaria em afiado :
sharp('input.jpg') .resize(200, 200) .toFile('ouput.jpg', function(err) { // output.jpg is a 200 pixels wide and 200 pixels high image // containing a scaled and cropped version of input.jpg });
É rápido, normalmente 6x mais rápido do que as ligações de nó mais rápidas baseadas em imagemagick e é executado em muito pouca memória, talvez 10x menos . links nítidos para a biblioteca de imagens libvips diretamente, não há transferência para um programa externo, e a própria biblioteca é mais rápida e eficiente do que * magick nesta tarefa. Ele suporta coisas úteis como fluxo, buffer e entrada e saída de sistema de arquivos, gerenciamento de cores, transparência, promessas, sobreposições, WebP, SVG e muito mais.
A partir de 0,20 afiado, o npm irá baixar automaticamente binários completos pré-compilados na maioria das plataformas, então não há necessidade de node-gyp. Basta inserir:
ou:
E pronto.
fonte
sharp
não há mais dependências de tempo de execução externas para usuários do Linux e Windows, pois inclui uma versão pré-compilada de libvips. Você descobrirá que as operações de redimensionamento são aproximadamente 10x mais rápidas do que o LWIP e com uma fração do uso da memória.npm install --global --production windows-build-tools
primeiro. Consulte também github.com/Microsoft/nodejs-guidelines/blob/master/…Recentemente comecei a desenvolver um módulo de processamento de imagem para NodeJS sem quaisquer dependências de tempo de execução ( leia porque ). Ainda está nos estágios iniciais, mas já pode ser usado.
O que você está pedindo seria feito da seguinte maneira:
image.resize(200, 200, function(err, image){ // encode resized image to jpeg and get a Buffer object image.toBuffer('jpg', function(err, buffer){ // save buffer to disk / send over network / etc. }); });
Mais informações no repositório Github do módulo .
fonte
writeFile
uma1.8Mb
imagem e requer 130 MB de memória. Depois disso, faço um teste redimensionando uma4MB, 11000x6000
imagem para várias miniaturas (640.560.480, ..., 160) e ela ocupa aproximadamente 1,7 GB de memória. Isso é um bug?Dê uma olhada em lwip: https://github.com/EyalAr/lwip
Muito simples e fácil de usar
e então em seu código de nó,
// obtain an image object: require('lwip').open('image.jpg', function(err, image){ // check err... // define a batch of manipulations and save to disk as JPEG: image.batch() .scale(0.75) // scale to 75% .rotate(45, 'white') // rotate 45degs clockwise (white fill) .crop(200) // crop a 200X200 square from center .blur(5) // Gaussian blur with SD=5 .writeFile('output.jpg', function(err){ // check err... // done. }); });
Eu implementei isso com sucesso no meu uploader de arquivos e funciona perfeitamente.
fonte
Existe uma boa biblioteca de manipulação de imagens escrita inteiramente em JavaScript, sem dependências de nenhuma outra biblioteca, Jimp. https://github.com/oliver-moran/jimp
Exemplo de uso:
var Jimp = require("jimp"); // open a file called "lenna.png" Jimp.read("lenna.png", function (err, lenna) { if (err) throw err; lenna.resize(256, 256) // resize .quality(60) // set JPEG quality .write("lena-small.jpg"); // save });
fonte
sharp tem desfrutado de alguma popularidade recentemente, mas é a mesma ideia que * ligações mágicas.
O redimensionamento da imagem é tudo menos simples. O formato JPEG é particularmente complexo e existem várias maneiras de dimensionar gráficos com resultados de qualidade variada, algumas delas facilmente implementadas. Existem bibliotecas de processamento de imagens para fazer esse trabalho, então se não houver outro motivo para você não poder instalá-las, vá em frente.
fonte
O Canvas é 2,3 vezes mais rápido que o ImageMagic.
Você pode tentar comparar módulos Node.js para manipulação de imagens - https://github.com/ivanoff/images-manipulation-performance
author's results: sharp.js : 9.501 img/sec; minFreeMem: 929Mb canvas.js : 8.246 img/sec; minFreeMem: 578Mb gm.js : 4.433 img/sec; minFreeMem: 791Mb gm-imagemagic.js : 3.654 img/sec; minFreeMem: 804Mb lwip.js : 1.203 img/sec; minFreeMem: 54Mb jimp.js : 0.445 img/sec; minFreeMem: 82Mb
fonte
Se você não precisa de uma imagem grande, pode redimensioná-la no lado do cliente antes de carregá-la:
Lendo arquivos em JavaScript usando APIs de arquivo
Redimensionar a imagem do lado do cliente com javascript antes de fazer upload para o servidor
Muitos usuários podem ter uma boa imagem de si mesmos em um smartphone, e muitos deles têm mais de 200 KB. Observe que os dados fornecidos pelo cliente não são confiáveis, portanto, as verificações do lado do servidor ainda se aplicam.
fonte
Eu estava usando o lwip (como sugerido anteriormente por arvind), mas mudei para o png-crop . Parece funcionar um pouco mais rápido para mim (Win 8.1 x64, Node v0.12.7). O código no repo parece incrivelmente leve e operacionalmente simples de usar.
var pngcrop = require('png-crop'); var config = {left: 10, top: 100, height: 150, width: 150}; pngcrop.crop('cats.png','cats-cropped.png',config);
Claro, só fará arquivos PNG ...
fonte
Sharp funciona muito bem e é fácil de usar com streams, funciona perfeitamente, mas você precisa compilá-lo com a versão do node, isso é uma desvantagem. Estava usando o Sharp para processamento de imagem, com uma imagem de um bucket AWS S3 e funcionou perfeitamente, mas tive que usar outro módulo. GM não funcionou para mim, mas Jimp funcionou muito bem!
Você tem que prestar atenção ao caminho da imagem escrita, pode haver alguns erros se você iniciar o caminho com um "/".
Foi assim que usei o Jimp no nodeJS:
const imageUrl = `SOME_URL`; let imgExported = 'EXPORTED_PIC.png'; Jimp.read(imageUrl) .then(image => { image .resize(X, Y) .write(`tmp/`+ imgExported, err => { if(err) console.error('Write error: ', err); else { ... // don't forget to put a callback() } } });
Também atente para a ordem de execução, coloque um callback para que outras coisas não aconteçam quando você não quiser. Tentei usar "await" para Jimp.read (), mas não funcionou bem.
fonte
Você pode fazer isso usando jimp (node_module)
Gravação local:
Jimp.read(path) // this can be url or local location .then(image=> { image .resize(size, Jimp.AUTO) // jimp.AUTO automatically sets the width so that the image doesnot looks odd .write('path-to-save'); }) .catch(err => { console.log(err); });
Para fazer upload para s3 ou onde quiser.
Jimp.read(urls) // this can be url or local location .then(image=> { image .resize(size, Jimp.AUTO) // jimp.AUTO automatically sets the width so that the image doesnot looks odd .getBase64(Jimp.AUTO, (err, res) => { const buf = new Buffer( res.replace(/^data:image\/\w+;base64,/, ""), "base64" ); var data = { Key: key, Bucket: bucket, Body: body, ContentEncoding: "base64", ContentType: "image/jpeg" }; s3.putObject(data, function(err, data) { if (err) { throw err; } else { console.log("succesfully uploaded the image!"); } }); }); }) .catch(err => { console.log(err); });
fonte
Eu gosto da biblioteca resize-img por sua simplicidade.
const fs = require('fs'); const resizeImg = require('resize-img'); (async () => { const image = fs.readFileSync('unicorn.png'); const newImage = await resizeImg(image, { width: 128, height: 128 }); fs.writeFileSync('unicorn-128x128.png', newImage); })();
fonte
Redimensionar imagem implementado usando Google Drive API v3 . Este método é recomendado para o Google Apps Script para inserir imagens no Google Sheets.
Algoritmo:
Veja o exemplo aqui: https://github.com/dobromyslov/google-drive-utils/blob/511c44c2c48862b47c60038423b7f71bf1d28f49/src/index.ts#L150
E cuidado com as cotas do GDrive:
fonte