web-dev-qa-db-ja.com

Node.js:ImageMagickを使用しない画像のサイズ変更

Node.js(+ express 4)でWebアプリを開発しています。ユーザーは、サーバーにアップロードしてプロフィール画像を設定できます。ファイルのmimetypeとmax filesizeは既に制限されているため、ユーザーは200KBを超えるpngまたはjpegイメージをアップロードできません。

問題は、ページの読み込みを改善し、ディスク上のスペースを節約するために、アップロードされた画像の解像度を200x200に変更(サーバー側)したいことです。いくつかの調査の後、すべての回答は、ImageMagickまたはGraphicsMagickに基づくモジュールを使用することを示しました。

ただし、単純な画像のサイズ変更を行うためにImageMagick/GraphicsMagickをインストールしなければならないのは私にはやりすぎだと思うので、Node.jsにこれ以外の解決策はありますか?

編集:以前のソリューション(lwip)が維持されなくなったため、受け入れられるソリューションを sharp に変更しました。すべてのフィードバックをありがとう!

70
zacr0

sharp :に投票します

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

通常、imagemagickベースの最速のノードバインディングよりも6倍高速 で、非常に少ないメモリで実行されます おそらく10倍少ないlibvips イメージライブラリへの直接リンク、外部プログラムへのシェルアウトはなく、ライブラリ自体はこのタスクで* magickよりも高速で効率的です。ストリーム、バッファ、ファイルシステムの入出力、色管理、透明度、プロミス、オーバーレイ、WebP、SVGなどの便利な機能をサポートしています。

シャープ0.20の時点で、npmはほとんどのプラットフォームでプリコンパイル済みの完全なバイナリを自動的にダウンロードするため、node-gypは必要ありません。以下を入力してください:

npm install sharp

または:

yarn add sharp

そして、出発です。

74
jcupitt

私は最近、ランタイム依存性のないNodeJS用の画像処理モジュールの開発を開始しました( read why )。まだ初期段階ですが、すでに使用可能です。

あなたが求めていることは次のように行われます:

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

詳細については、モジュールの Githubリポジトリ を参照してください。

70
EyalAr

Lwipを見てください: https://github.com/EyalAr/lwip

非常にシンプルで使いやすい

npm install lwip

そして、ノードコードで、

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

});

file uploader でこれを正常に実装しました。これは魅力のように機能します。

16
Arvind

JavaScriptで完全に記述された、他のライブラリJimpに依存しない優れた画像操作ライブラリがあります。 https://github.com/oliver-moran/jimp

使用例:

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 は最近人気を博していますが、これは* Magickバインディングと同じ考えです。

しかし、ImageMagick/GraphicsMagickをインストールして単純な画像のサイズ変更を行う必要があるのは、私にとってはやりすぎだ

画像のサイズ変更は簡単ではありません。 JPEG形式は特に複雑で、さまざまな品質の結果でグラフィックをスケーリングする方法はいくつかありますが、簡単に実装できるものはほとんどありません。このジョブを実行するための画像処理ライブラリが存在するため、インストールできない他の理由がない場合は、それを選択してください。

8
Ry-

CanvasはImageMagicより2.3倍高速です

画像操作のためにNode.jsモジュールを比較することができます- 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

大きな画像が必要ない場合は、アップロードする前にクライアント側でサイズを変更できます。

ファイルAPIを使用してJavaScriptでファイルを読み取る

サーバーにアップロードする前にJavaScriptでクライアント側のサイズを変更する画像

多くのユーザーは、スマートフォンから自分自身の良い写真を持っているかもしれませんし、それらの多くは200kB以上です。クライアントが提供するデータは信頼されないため、サーバー側のチェックが引き続き適用されることに注意してください。

3
Andrei Volgin

私は(以前にarvindによって提案されたように)lwipを使用していましたが、 png-crop に切り替えました。私にとっては少し速く動作するようです(Win 8.1 x64、Node v0.12.7)。リポジトリ内のコードは信じられないほど軽量に見え、操作上は簡単に使用できます。

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

もちろん、PNGファイルのみを実行します...

1
Dan Caseley

Sharpは非常にうまく機能し、ストリームで簡単に使用でき、チャームのように機能しますが、ノードバージョンでコンパイルする必要があります。これは欠点です。 AWS S3バケットからの画像を使用して、画像処理にSharpを使用し、完全に機能しましたが、別のモジュールを使用する必要がありました。 GMはうまくいきませんでしたが、Jimpはとてもうまくいきました!

書かれた画像のパスに注意を払う必要があります。「/」でパスを開始すると、エラーが発生する可能性があります。

これは、nodeJSでJimpを使用した方法です。

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

            });

また、実行の順序に注意し、必要のないときに他のことが起こらないようにコールバックを設定します。 Jimp.read()に "await"を使用してみましたが、うまくいきませんでした。

0
Alex Seceleanu

Jimp(node_module)を使用してこれを行うことができます

ローカル書き込み:

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

s3または任意の場所にアップロードします。

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