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


86

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

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

ただし、単純な画像のサイズ変更を行うためにImageMagick / GraphicsMagickをインストールする必要があるのは、私にはやり過ぎに思えます。それで、Node.jsに対してこれ以外の解決策はありますか?

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


こんにちは。質問があります。画像サイズを200KB未満に縮小するにはどうすればよいですか?方法を説明してください。ありがとう。
C.Petrescu 2017年

こんにちは。以前に投稿された関連する質問が見つからない場合は、その質問を新しい質問として投稿する価値があります。少し光を当てるために、この質問で見つけることができるツール用に提供されているAPIで圧縮およびサイズ変更の方法を探してみてください。
zacr0 2017年

回答:


92

私はシャープに投票します:

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分の1になります。libvipsイメージライブラリへの直接のシャープなリンク。外部プログラムへのシェルアウトはなく、ライブラリ自体はこのタスクで* magickよりも高速で効率的です。ストリーム、バッファ、ファイルシステムの入出力、カラーマネジメント、透明度、プロミス、オーバーレイ、WebP、SVGなどの便利な機能をサポートしています。

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

npm install sharp

または:

yarn add sharp

そして、あなたは行き​​ます。


7
v0.12.0以降、sharpコンパイル済みバージョンのlibvipsがバンドルされているため、LinuxおよびWindowsユーザーの外部ランタイム依存関係はなくなりました。サイズ変更操作はLWIPよりも約10倍高速で、メモリ使用量のほんの一部であることがわかります。
Lovell Fuller

4
バージョン0.15を持つ鋭い加えネイティブGIFとSVGサポートsharp.dimens.io/en/stable/changelog
jcupitt

1
数百のファイルですが、それらはすべてnpmによって自動的に管理されるため、考える必要はありません。
jcupitt 2016年

4
@CoDEmanXおそらくnpm install --global --production windows-build-tools最初に実行してみてください。github.com/Microsoft/nodejs-guidelines/blob/master/
Lovell Fuller

1
私は小さなスクリプトは、それが簡単にできるようになり建て見る何をやっているし、それがブートストラップカードや背景などのコンテンツにどのように見えるか:多分そのintrestの最良の最適化するために、カバーのparams、github.com/lcherone/sharp-test
ローレンスCherone

71

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

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

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リポジトリをご覧ください。


7
あなたのモジュールは素晴らしいです。ただし、非常に多くのメモリが必要です。画像を試しましwriteFile1.8Mbが、130Mbのメモリが必要です。その後、4MB, 11000x6000画像のサイズをいくつかのサムネイル(640,560,480、...、160)に変更してテストを行いますが、約1.7GBのメモリが必要です。それはバグですか?
ルイス

2
こんにちは@Orion、フィードバックをありがとう。Githubリポジトリにアクセスして、詳細(OS、バージョン、これを再現するためのコード)で問題を開いてください。私たちは一緒にこれを解決しようとします:)
EyalAr 2014年

@EyalArねえ、Eyal、サイズを変更してアスペクトを維持する方法は?(幅、高さの可能な最大サイズにサイズ変更)ストレッチなし
Daniel Krom 2016

10
2017年にはlwipを使用しないことをお勧めします。パッケージはサポートされなくなったようで、Windows、さらにはUnixプラットフォームでも大きなインストールの問題があります。
zerefel 2017年

9
残念ながら、lwipは死んだプロジェクトです。しかし、シャープはまだ積極的に維持されているようです。
laurent 2017年

16

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

});

私はこれをファイルアップローダーに正常に実装しました。これは魅力のように機能します


1
これは私が探していたものであり、画像のサイズ変更に関連するいくつかの機能のために、過剰な外部依存関係をインストールする必要はありません。
zacr0 2014年

3
ところで、@ EyalArはこのノードモジュールの作者です。彼のコメントも以下にリストされています。
Arvind

インストールと操作が非常に直感的です。ImageMagickのようなバイナリライブラリを実装する必要がないのが本当に好きです。
ChrisRich 2015年

この答え(のlwIPの所有者)と全く同じですが、後でその:stackoverflow.com/a/24543924/1525495
ホルヘ・フエンテス・ゴンサレス

12

他のライブラリ、Jimpに依存することなく、完全にJavaScriptで記述された優れた画像操作ライブラリがあります。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
});

ImageMagikと比較してこれはどれくらい速いですか?
クリストファーグリッグ2016

2
シャープには一連のベンチマークがあります:sharp.dimens.io/en/stable/performance ---そのテストでは、ジンプはIMより5倍遅く、シャープより30倍遅いです。もちろん、十分に速いことは十分に速いことであり、考慮すべき要素は速度だけではありません。
jcupitt 2016

リアルタイムではないかもしれませんが、Jimpは、複数サイズのサムネイルファイルを書き込む(そして後でキャッシュファイルとして取得する)のに最適です。
coderofsalvation 2017年

jimpはwebpをサポートしておらず、近い将来サポートしなくなります。参照:github.com/oliver-moran/jimp/issues/144
ViacheslavDobromyslov20年

8

シャープは最近人気を博していますが、それは* Magickバインディングと同じ考えです。

ただし、単純な画像のサイズ変更を行うためにImageMagick / GraphicsMagickをインストールする必要があるのは、私にはやり過ぎのようです。

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


13
私は怠惰な開発者かもしれませんが、ImageMagickのインストールプロセスを見て、Amazon AWS EC2インスタンスへのインストールにいくら費やすのか疑問に思ったら、すぐに他のオプションを探し始めました-特に必要なのはサムネイルの画像のサイズを変更する機能。
ChrisRich 2015年

7

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

3

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

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

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

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


2
クライアントを信頼することはできません。ユーザーはアップロードエンドポイントを知っているだけで、必要なものを送信できます。したがって、ファイルサイズなどの検証は引き続き適用されます。ただし、クライアント側でサイズを変更することをお勧めします。
Kev 2015年

1

私はlwipを使用していましたが(以前にarvindによって提案されたように)、png-cropに切り替えました。私にとっては少し速く動作するようです(Win 8.1 x64、ノード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ファイルのみを実行します...


0

シャープは非常にうまく機能し、ストリームで簡単に使用でき、魅力のように機能しますが、ノードバージョンでコンパイルする必要があります。これは欠点です。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.20から、ほとんどのプラットフォームで正確なノードバージョン用にコンパイル済みのバイナリが自動的にダウンロードされるため、何もビルドする必要はありません。
jcupitt

残念ながら、それは私にとってはうまくいきませんでした。さまざまなnode.jsバージョンの読み取り専用ファイルシステムでsharpを使用する必要があり、使用しているノードバージョンごとにsharpモジュールをダウンロードする必要があり、時間がかかりすぎました。
AlexSeceleanu19年

0

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

私はその単純さのためにresize-imgライブラリが好きです。

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

0

Google Drive APIv3を使用して画像のサイズ変更を実装。この方法は、Google AppsScriptで画像をGoogleスプレッドシートに挿入する場合に推奨されます。

アルゴリズム:

  1. アップロードGoogleドライブフォルダに画像をます。
  2. 取得する画像サムネイルの公開URLをます。
  3. URLの「resize」パラメータを必要な幅や高さに置き換えます。(デフォルトのサムネイルサイズは220pxです)。
  4. サイズ変更されたサムネイルをGoogleドライブからダウンロードします。

ここの例を参照してください: ご覧ください https //github.com/dobromyslov/google-drive-utils/blob/511c44c2c48862b47c60038423b7f71bf1d28f49/src/index.ts#L150

また、GDriveの割り当てに注意してください。

  • 1日あたりのクエリ:1000000000
  • ユーザーあたり100秒あたりのクエリ:1000
  • 100秒あたりのクエリ:10000
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.