くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Node.jsライブラリのsharpで画像処理をいろいろしてみた

開発しているWebサービスでOGP画像を良くしたいなと思い、
Node.jsライブラリのsharpが良さそうだったので、いろいろ調べてみたときの備忘録。
ImageMagickの4〜5倍、高速らしい...

できたのはこんなかんじ(´ω`)

インストール

インストールはこんな感じ

$ npm i sharp

リサイズ

画像サイズの変更は、resizeを使えばOK。

指定なしだとcoverだけど、containfillなども指定できる。

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で使えるようなので今度試してみたい。

以上!!

参考にしたサイト様