Node.js(+ express 4)でWebアプリを開発しています。ユーザーは、サーバーにアップロードしてプロフィール画像を設定できます。ファイルのmimetypeとmax filesizeは既に制限されているため、ユーザーは200KBを超えるpngまたはjpegイメージをアップロードできません。
問題は、ページの読み込みを改善し、ディスク上のスペースを節約するために、アップロードされた画像の解像度を200x200に変更(サーバー側)したいことです。いくつかの調査の後、すべての回答は、ImageMagickまたはGraphicsMagickに基づくモジュールを使用することを示しました。
ただし、単純な画像のサイズ変更を行うためにImageMagick/GraphicsMagickをインストールしなければならないのは私にはやりすぎだと思うので、Node.jsにこれ以外の解決策はありますか?
編集:以前のソリューション(lwip)が維持されなくなったため、受け入れられるソリューションを sharp に変更しました。すべてのフィードバックをありがとう!
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
そして、出発です。
私は最近、ランタイム依存性のない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リポジトリ を参照してください。
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 でこれを正常に実装しました。これは魅力のように機能します。
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
});
sharp は最近人気を博していますが、これは* Magickバインディングと同じ考えです。
しかし、ImageMagick/GraphicsMagickをインストールして単純な画像のサイズ変更を行う必要があるのは、私にとってはやりすぎだ
画像のサイズ変更は簡単ではありません。 JPEG形式は特に複雑で、さまざまな品質の結果でグラフィックをスケーリングする方法はいくつかありますが、簡単に実装できるものはほとんどありません。このジョブを実行するための画像処理ライブラリが存在するため、インストールできない他の理由がない場合は、それを選択してください。
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
大きな画像が必要ない場合は、アップロードする前にクライアント側でサイズを変更できます。
ファイルAPIを使用してJavaScriptでファイルを読み取る
サーバーにアップロードする前にJavaScriptでクライアント側のサイズを変更する画像
多くのユーザーは、スマートフォンから自分自身の良い写真を持っているかもしれませんし、それらの多くは200kB以上です。クライアントが提供するデータは信頼されないため、サーバー側のチェックが引き続き適用されることに注意してください。
私は(以前に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ファイルのみを実行します...
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"を使用してみましたが、うまくいきませんでした。
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);
});