Node.jsのライブラリsharpでEXIFなどの画像情報を取得してみる

sharpを使って情報を取得してみました。

  • meta情報を取得
  • EXIF情報を取得
  • 画像情報を取得
  • だいたいの明るさを調べる

準備

npm install sharp

meta情報を取得

画像のmeta情報を取得して表示してみます。

const sharp = require('sharp')

sharp('IMG_5963.jpg')
  .metadata()
  .then(function(metadata) {
    console.log(metadata)
  })

出力結果

{ format: 'jpeg',
  width: 5411,
  height: 3607,
  space: 'srgb',
  channels: 3,
  depth: 'uchar',
  density: 240,
  chromaSubsampling: '4:4:4',
  isProgressive: false,
  hasProfile: true,
  hasAlpha: false,
  exif:
   <Buffer 45 78 69 66 00 00 49 49 2a 00 08 00 00 00 08 00 0f 01 02 00 06 00 00 00 6e 00 00 00 10 01 02 00 15 00 00 00 74 00 00 00 1a 01 05 00 01 00 00 00 8a 00 ... 16279 more bytes>,
  icc:
   <Buffer 00 00 0c 48 4c 69 6e 6f 02 10 00 00 6d 6e 74 72 52 47 42 20 58 59 5a 20 07 ce 00 02 00 09 00 06 00 31 00 00 61 63 73 70 4d 53 46 54 00 00 00 00 49 45 ... 3094 more bytes>,
  iptc:
   <Buffer 50 68 6f 74 6f 73 68 6f 70 20 33 2e 30 00 38 42 49 4d 03 ed 00 00 00 00 00 10 00 f0 00 00 00 01 00 01 00 f0 00 00 00 01 00 01 38 42 49 4d 04 04 00 00 ... 15634 more bytes>,
  xmp:
   <Buffer 68 74 74 70 3a 2f 2f 6e 73 2e 61 64 6f 62 65 2e 63 6f 6d 2f 78 61 70 2f 31 2e 30 2f 00 3c 3f 78 70 61 63 6b 65 74 20 62 65 67 69 6e 3d 22 ef bb bf 22 ... 13056 more bytes> }

EXIF情報を取得

npm install exif-reader

EXIF情報を読み取るにはexif-readerというライブラリを追加します。

const sharp = require('sharp')
const exif = require('exif-reader')

sharp('IMG_5963.jpg')
  .metadata()
  .then(function(metadata) {
    console.log(exif(metadata.exif))
  })

出力結果

{ image:
   { Make: 'Canon',
     Model: 'Canon EOS 5D Mark II',
     XResolution: 240,
     YResolution: 240,
     ResolutionUnit: 2,
     Software: 'Adobe Photoshop Lightroom Classic 8.2 (Macintosh)',
     ModifyDate: 2019-02-23T18:32:58.000Z,
     ExifOffset: 224 },
  thumbnail:
   { Compression: 6,
     XResolution: 72,
     YResolution: 72,
     ResolutionUnit: 2,
     ThumbnailOffset: 826,
     ThumbnailLength: 15497 },
  exif:
   { ExposureTime: 0.03333333333333333,
     FNumber: 10,
     ExposureProgram: 3,
     ISO: 100,
     ExifVersion: <Buffer 30 32 33 30>,
     DateTimeOriginal: 2019-02-23T14:37:25.000Z,
     DateTimeDigitized: 2019-02-23T14:37:25.000Z,
     ShutterSpeedValue: 4.906891,
     ApertureValue: 6.643856,
     ExposureBiasValue: -0.6666666666666666,
     MaxApertureValue: 4,
     MeteringMode: 5,
     Flash: 16,
     FocalLength: 25,
     SubSecTimeOriginal: '29',
     SubSecTimeDigitized: '29',
     ColorSpace: 1,
     FocalPlaneXResolution: 3849.2117888965045,
     FocalPlaneYResolution: 3908.141962421712,
     FocalPlaneResolutionUnit: 2,
     CustomRendered: 0,
     ExposureMode: 0,
     WhiteBalance: 0,
     SceneCaptureType: 0,
     BodySerialNumber: '1090600231',
     LensSpecification: [ 16, 35, NaN, NaN ],
     LensModel: 'EF16-35mm f/4L IS USM' } }

画像情報を取得

const sharp = require('sharp')

sharp('IMG_5963.jpg')
  .stats()
  .then(function(status) {
    console.log(status)
  })

出力結果

チャンネルごとにそれぞれの値を持っています。

キー名 意味
min 最小値
max 最大値
sum 合計値
squaresSum 二乗の合計値
mean 平均値
stdev 分散値
minX 最小値のピクセルのあるx座標
minY 最小値のピクセルのあるy座標
maxX 最大値のピクセルのあるx座標
maxY 最大値のピクセルのあるy座標
{ channels:
   [ { min: 0,
       max: 255,
       sum: 1703883795,
       squaresSum: 205193944135,
       mean: 87.30041259943587,
       stdev: 53.77714963014096,
       minX: 4194,
       minY: 2000,
       maxX: 2322,
       maxY: 96 },
     { min: 0,
       max: 255,
       sum: 1585252287,
       squaresSum: 180140805013,
       mean: 81.22219316564329,
       stdev: 51.30958272260924,
       minX: 5408,
       minY: 1878,
       maxX: 2322,
       maxY: 96 },
     { min: 0,
       max: 255,
       sum: 1456110085,
       squaresSum: 165358763715,
       mean: 74.60544644166866,
       stdev: 53.910766262490625,
       minX: 3846,
       minY: 0,
       maxX: 2322,
       maxY: 96 } ],
  isOpaque: true,
  entropy: 7.184138543480117 }

だいたいの明るさを調べる

ピクセルの平均値を調べることで画像のだいたいの明るさがわかります。

sharp('sea.jpg')
  .stats()
  .then(function(metadata) {
    const channels = metadata.channels
    const sum =
      channels
        .map(channel => channel.mean)
        .reduce((prv, cur)=> {return prv+cur})
    console.log(sum / channels.length)
  })

sea.jpg

cats.jpgよりも明るいため値が大きくなっています。

値:178.84236200207724

海の画像

cats.jpg

値:81.09800563599707

ねこの画像