開発しているWebサービスでOGP画像を良くしたいなと思い、
Node.jsライブラリのsharpが良さそうだったので、いろいろ調べてみたときの備忘録。
ImageMagickの4〜5倍、高速らしい...
できたのはこんなかんじ(´ω`)
積読金額や読了金額のシェア画像も改善🚀
— めもらば@公式 (@MemoryLoverz) February 8, 2020
お札になれちゃうアプリになりました😊
(続く pic.twitter.com/qTL5VHMTjq
インストール
インストールはこんな感じ
$ npm i sharp
リサイズ
画像サイズの変更は、resize
を使えばOK。
指定なしだとcover
だけど、contain
やfill
なども指定できる。
const sharp = require('sharp') await sharp('input.jpg') .resize(512, 200) .toFile('output.jpg');
- 参考
グレイスケール
画像変換もできる。グレイスケールはこんな感じ。
ぼかし(blur
)や回転(rotate
)などもあり、同じ感じで使える。
const sharp = require('sharp') await sharp('input.jpg') .grayscale() .toFile('output.jpg');
- 参考
丸い形に切り取る
画像を合成したり、加工したりする場合は、composite
を使う。
丸い形など特定の形で切り取る場合は、
SVGで形を作ってdest-in
で合成するのが良い感じ。
const sharp = require('sharp'); const width = 400; const r = width / 2; const circleShape = Buffer.from(`<svg><circle cx="${r}" cy="${r}" r="${r}" /></svg>`); await sharp('input.jpg') .resize(width, width) .composite([{ input: circleShape, blend: 'dest-in' }]) .png() .toFile('output.png');
今回、実装したようなユーザアイコンを丸く加工して、
背景画像と合成するのはこんな感じ。
const sharp = require('sharp'); const width = 400; const r = width / 2; const circleShape = Buffer.from(`<svg><circle cx="${r}" cy="${r}" r="${r}" /></svg>`); // アイコン画像を丸い形で加工 const iconBuffer = await sharp('icon.jpg') .png() // ※元画像がjpgの場合は、pngにして透過できるようにする .resize(width, width) .composite([{ input: circleShape, blend: 'dest-in' }]) .toBuffer(); // 加工したicon画像を背景画像の中心に合成 await sharp("background.png") .composite([{ input: iconBuffer, gravity: "center", blend: "hard-light" }]) .png() .toFile('output.png');
注意点としては、加工する前にpng形式に変換しておくことが大事。
jpgは透過がないため、pngに変換しないと、背景が黒くなってしまう。。
SharpでOGP生成してみた感想
画像の加工、合成だけならsharpが便利。ImageMagickよりも簡単にできる。
Cloud Function for Firebaseでも利用できるので、
リサイズも合成サクッとできるのでいい感じ。
ただ、SVGを入力とする場合は、
カスタムフォントやforeignObjectがあまり使えないので注意が必要。
issueをみるとSVG関連のライブラリ自体対応していないので期待薄。。
当初は、SVGをそのままPNG出力しようとしていたけど、
上記の制約によりうまくいかず、画像合成部分だけsharpを使い、
文字の部分だけ、ImageMagickで書き出している感じ。
puppeteerもCloud Function for Firebaseで使えるようなので今度試してみたい。
以上!!