web-dev-qa-db-fra.com

Node.js: image redimensionnant sans ImageMagick

Je développe une application Web sur Node.js (+ express 4) où les utilisateurs peuvent définir l'image de leur profil en la téléchargeant sur le serveur. Nous limitons déjà le type de fichier et la taille maximale du fichier, de sorte que l'utilisateur ne peut pas télécharger plus de 200 Ko d'images png ou jpeg.

Le problème est que nous aimerions redimensionner (au niveau du serveur) la résolution de l'image téléchargée à 200x200 pour améliorer le chargement de la page et économiser de l'espace sur le disque. Après quelques recherches, toutes les réponses suggèrent d’utiliser un module basé sur ImageMagick ou GraphicsMagick.

Cependant, avoir à installer ImageMagick/GraphicsMagick pour effectuer un simple redimensionnement d'image me semble trop coûteux, alors existe-t-il une solution autre que celle-ci pour Node.js?

Edit: J'ai changé la solution acceptée en sharp car la solution précédente (lwip) n'est plus maintenue. Merci pour tous vos commentaires!

70
zacr0

Je voterais pour forte :

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
  });

C'est rapide, généralement 6 fois plus rapide que les liaisons de nœud les plus rapides basées sur imagemagick , et fonctionne très peu en mémoire, peut-être 10 fois moins . Des liens pointus vers la bibliothèque d'images libvips directement, il n'y a pas de programme à exécuter, et la bibliothèque elle-même est plus rapide et plus efficace que * magick pour cette tâche. Il prend en charge des éléments utiles tels que les entrées et les sorties de flux, de mémoire tampon et de système de fichiers, la gestion des couleurs, la transparence, les promesses, les superpositions, WebP, SVG, etc.

À partir de sharp 0.20, npm téléchargera automatiquement des fichiers binaires pré-compilés complets sur la plupart des plateformes. Il n’est donc pas nécessaire de recourir à node-gyp. Il suffit d'entrer:

npm install sharp

ou:

yarn add sharp

Et c'est parti.

74
jcupitt

J'ai récemment commencé à développer un module de traitement d'image pour NodeJS sans aucune dépendance à l'exécution ( lisez pourquoi ). Il est encore à ses débuts, mais déjà utilisable.

Ce que vous demandez serait fait comme suit:

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.
    });
});

Plus d'infos sur le module Github repo .

70
EyalAr

Jetez un oeil à lwip: https://github.com/EyalAr/lwip

Très simple et facile à utiliser

npm install lwip

puis dans votre code de noeud,

// 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.
    });

});

J'ai réussi à implémenter cela dans mon ploader un fichier et cela fonctionne à merveille.

16
Arvind

Il existe une bonne bibliothèque de manipulation d'images entièrement écrite en JavaScript, qui ne dépend d'aucune autre bibliothèque, Jimp. https://github.com/oliver-moran/jimp

Exemple d'utilisation:

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
});
10
edtech

sharp jouit d’une certaine popularité récemment, mais c’est la même idée que les liaisons * Magick.

Cependant, avoir à installer ImageMagick/GraphicsMagick pour effectuer un simple redimensionnement d'image me semble trop coûteux

Le redimensionnement de l'image est tout sauf simple. Le format JPEG est particulièrement complexe et il existe plusieurs manières de redimensionner les graphiques avec des résultats de qualité variable, dont peu sont facilement implémentés. Des bibliothèques de traitement d’images existent pour faire ce travail. Par conséquent, s’il n’ya aucune autre raison pour laquelle vous ne pouvez pas les installer, n'hésitez pas.

8
Ry-

Le canevas est 2,3 fois plus rapide que ImageMagic.

Vous pouvez essayer de comparer les modules Node.js pour la manipulation d’images - 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
5
Dimitry Ivanov

Si vous n'avez pas besoin d'une grande image, vous pouvez la redimensionner côté client avant de la télécharger:

Lecture de fichiers en JavaScript à l'aide des API de fichiers

Image redimensionnant côté client avec javascript avant téléchargement sur le serveur

De nombreux utilisateurs peuvent avoir une bonne image d'eux-mêmes à partir d'un smartphone, et beaucoup d'entre eux ont plus de 200 Ko. Notez que les données fournies par le client ne doivent pas être approuvées. Par conséquent, les contrôles côté serveur s'appliquent toujours.

3
Andrei Volgin

J'utilisais lwip (comme suggéré précédemment par arvind) mais suis passé à png-crop . Cela semble fonctionner un peu plus vite pour moi (Win 8.1 x64, Node v0.12.7). Le code dans le repo est incroyablement léger et, du point de vue opérationnel, il est simple à utiliser.

var pngcrop = require('png-crop');
var config = {left: 10, top: 100, height: 150, width: 150};
pngcrop.crop('cats.png','cats-cropped.png',config);

Bien sûr, il ne fera que des fichiers png ...

1
Dan Caseley

Sharp fonctionne très bien et est facile à utiliser avec les flux, fonctionne comme un charme, mais vous devez le compiler avec la version du nœud, c’est un inconvénient. J'utilisais Sharp pour le traitement des images, avec une image d'un compartiment AWS S3 et fonctionnait parfaitement, mais je devais utiliser un autre module. GM n'a pas fonctionné pour moi, mais Jimp a très bien fonctionné!

Vous devez faire attention au chemin de l'image écrite, cela pourrait vous donner des erreurs si vous démarrez le chemin avec un "/".

Voici comment j'ai utilisé Jimp dans 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() } }

            });

Faites également attention à l'ordre d'exécution, mettez un rappel pour que rien ne se passe si vous ne le souhaitez pas. J'ai essayé d'utiliser "wait" pour Jimp.read () mais cela n'a pas bien fonctionné.

0
Alex Seceleanu

Vous pouvez le faire en utilisant jimp (node_module)

écriture locale:

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);
      });

Pour télécharger sur s3 ou où vous voulez.

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);
          });
0
Nouman Dilshad