これからはじめるGulp #16:gulp-image-resizeプラグインを使ってサムネイルやレスポンシブイメージを作る

2014.12.16

はじめに

前回のこれからはじめるGulp(15):gulp-responsiveプラグインを使ったレスポンシブイメージ作成の自動化でNode.js向け画像処理ライブラリを使ったレスポンシブイメージ作成の自動化を行いました。今回はより手軽に使えるgulp-image-resizeプラグインを使いサムネイル画像を作ってみたいと思います。

gulp-image-resizeについて

gulp-image-resizeは画像のリサイズや切り抜きができるプラグインです。gulp-image-resizeを使うにはImageMagickGraphicsMagickが必要です。

ImageMagick or GraphicsMagickのインストール

どちらもHomebrewを使ってインストールします。どちらか一方でかまいませんが、ImageMagickを使うにはオプション指定が必要になります。今回はオプションの指定方法も説明するのであえてImageMagickを使います。

ImageMagickのインストール方法

今回はこちらをインストールします。

$ brew install imagemagick

Graphicsmagickのインストール方法

$ brew install graphicsmagick

gulp-image-resizeのインストール

続いて、gulp-image-resizeプラグイン本体をインストールします。

$ sudo npm install --save-dev gulp-image-resize
Password:
gulp-image-resize@0.5.0 node_modules/gulp-image-resize
├── async@0.2.10
├── through2@0.4.2 (xtend@2.1.2, readable-stream@1.0.33)
├── lodash@2.4.1
├── gulp-gm@0.0.7 (gm@1.17.0)
└── gulp-util@2.2.20 (lodash._reinterpolate@2.4.1, minimist@0.2.0, vinyl@0.2.3, chalk@0.5.1, through2@0.5.1, multipipe@0.1.2, dateformat@1.0.11, lodash.template@2.4.1)

サムネイルを作成するタスク

141枚のスクリーンキャプチャを用意し、サムネイル画像を作ってみます。まずは横200px:縦200pxの画像の中心を基準にしたサムネイルを作成し、gulp-imageminプラグインと連携して軽量化するタスクを作ります。このタスクにはgulp-changedプラグインとと処理されたファイル名をログに流すgulp-filelogプラグインを使います。gulp-filelogを使うことでタスクの進捗を把握します。

var gulp        = require('gulp');
var changed     = require('gulp-changed'); 
var filelog     = require('gulp-filelog');
var imageResize = require('gulp-image-resize');
var imagemin    = require('gulp-imagemin');

var paths = {
  srcDir : 'src',
  prvDir : 'prv',
  dstDir : 'prd',
  uploadsDir: '/uploads'
}

gulp.task( 'image-optim:thumb', function(){
  var baseDir  = paths.srcDir + paths.uploadsDir + '/origin';
  var srcGlob  = paths.srcDir + paths.uploadsDir + '/origin/**/*.+(jpg|jpeg|png|gif)';
  var dstGlob  = paths.dstDir + paths.uploadsDir + '/thumb';

  var resizeOptions = {
    width       : 200,
    height      : 200,
    gravity     : 'Center',
    crop        : true,
    upscale     : false,
    imageMagick : true
  };

  var imageminOptions = {
    optimizationLevel: 7
  };

  return gulp.src( srcGlob, { base: baseDir } )
    .pipe(changed( dstGlob ))
    .pipe(imageResize( resizeOptions ))
    .pipe(imagemin( imageminOptions ))
    .pipe(gulp.dest( dstGlob ))
    .pipe(filelog());
});

リサイズオプションの指定はこのようになります。imageMagick : trueがImageMagickを使うための指定です。

var resizeOptions = {
    width       : 200,
    height      : 200,
    gravity     : 'Center',
    crop        : true,
    upscale     : false,
    imageMagick : true
  };

image-optim:thumbタスクの実行

タスクを実行してみます(長すぎるので途中を省いています)。

$ gulp image-optim:thumb
[00:00:04] Using gulpfile ~/Projects/gulp.whiskers.nukos.kitchen/gulpfile.js
[00:00:04] Starting 'image-optim:thumb'...
[00:00:05] [1] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gifbrewery/animation_gif.gif]
[00:00:06] [2] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gifbrewery/capture_tool.png]
[00:00:08] [3] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gr/gr_photo_001.jpg]
[00:00:08] [4] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gr/gr_photo_002.jpg]
[00:00:09] [5] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gifbrewery/crop.png]
[00:00:10] [6] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gifbrewery/open_gifbrewery.png]
[00:00:10] [7] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/08/gifbrewery/gif_animation.png]
[00:00:10] [8] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/06/start/thumbnail_960.png]
[00:00:11] [9] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/09/monotony/kimonolabs.png]
…
[00:01:45] gulp-imagemin: Minified 141 images (saved 647.91 kB - 22%)
[00:01:45] [141] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/11/high-performance-browser-networking-meetup/thumbnail.png]
[00:01:45] Found [141] files.
[00:01:45] Finished 'image-optim:thumb' after 1.68 min

141個のサムネイル作成に1分45秒かかり、22%軽量化できました。[/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb/2014/09/monotony/kimonolabs.png]がgulp-filelogが出力したログです。もう一度タスクを実行するとgulp-chagedが効き処理が省略されます。

$ gulp image-optim:thumb
[02:52:40] Using gulpfile ~/Projects/gulp.whiskers.nukos.kitchen/gulpfile.js
[02:52:40] Starting 'image-optim:thumb'...
[02:52:41] gulp-imagemin: Minified 0 images (saved 0 B - 0%)
[02:52:41] Found [0] files.
[02:52:41] Finished 'image-optim:thumb' after 318 ms

変更されたファイルがあればそのファイルのみ処理させることができます。

高解像度ディスプレイ用のサムネイルとミドルサイズの画像を作る

追加で2種類の画像とオリジナル画像を軽量化するタスクを作ります。この3種類タスクは管理しやすくするため別々のタスクとします。

400*400のサムネイルを作るタスク

//create thumb 2x size
gulp.task( 'image-optim:thumb-2x', function(){
  var baseDir  = paths.srcDir + paths.uploadsDir + '/origin';
  var srcGlob  = paths.srcDir + paths.uploadsDir + '/origin/**/*.+(jpg|jpeg|png|gif)';
  var dstGlob  = paths.dstDir + paths.uploadsDir + '/thumb-2x';

  var resizeOptions = {
    width       : 400,
    height      : 400,
    gravity     : 'Center',
    crop        : true,
    upscale     : false,
    imageMagick : true
  };

  var imageminOptions = {
    optimizationLevel: 7
  };

  return gulp.src( srcGlob, { base: baseDir } )
    .pipe(changed( dstGlob ))
    .pipe(imageResize( resizeOptions ))
    .pipe(imagemin( imageminOptions ))
    .pipe(gulp.dest( dstGlob ))
    .pipe(filelog());
});

ミドルサイズの画像を作るタスク

//create middle size
gulp.task( 'image-optim:middle', function(){
  var baseDir  = paths.srcDir + paths.uploadsDir + '/origin';
  var srcGlob  = paths.srcDir + paths.uploadsDir + '/origin/**/*.+(jpg|jpeg|png|gif)';
  var dstGlob  = paths.dstDir + paths.uploadsDir + '/middle';

  var resizeOptions = {
    width       : 960,
    upscale     : false,
    imageMagick : true
  };

  var imageminOptions = {
    optimizationLevel: 7
  };

  return gulp.src( srcGlob, { base: baseDir } )
    .pipe(changed( dstGlob ))
    .pipe(imageResize( resizeOptions ))
    .pipe(imagemin( imageminOptions ))
    .pipe(gulp.dest( dstGlob ))
    .pipe(filelog());
});

オリジナル画像を軽量化するタスク

//optimize origin
gulp.task( 'image-optim:origin', function(){
  var baseDir  = paths.srcDir + paths.uploadsDir + '/origin';
  var srcGlob  = paths.srcDir + paths.uploadsDir + '/origin/**/*.+(jpg|jpeg|png|gif|svg)';
  var dstGlob  = paths.dstDir + paths.uploadsDir + '/origin';

  var imageminOptions = {
    optimizationLevel: 7
  };

  return gulp.src( srcGlob, { base: baseDir } )
    .pipe(changed( dstGlob ))
    .pipe(imagemin( imageminOptions ))
    .pipe(gulp.dest( dstGlob ))
    .pipe(filelog());
});

それぞれのタスクを非同期処理させるようimage-optimというタスクを作ります。

gulp.task( 'image-optim', ['image-optim:thumb', 'image-optim:thumb-2x', 'image-optim:middle', 'image-optim:origin']);

image-optimタスクを実行する

image-optimタスクですべての画像処理を実行します。4つのタスクが非同期で処理されます。

$ gulp image-optim
[02:57:08] Using gulpfile ~/Projects/gulp.whiskers.nukos.kitchen/gulpfile.js
[02:57:08] Starting 'image-optim:thumb'...
[02:57:08] Starting 'image-optim:thumb-2x'...
[02:57:08] Starting 'image-optim:middle'...
[02:57:08] Starting 'image-optim:origin'...
[02:57:09] gulp-imagemin: Minified 0 images (saved 0 B - 0%)
[02:57:09] Found [0] files.
[02:57:09] Finished 'image-optim:thumb' after 1.06 s
[02:57:09] [1] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/08/gifbrewery/animation_gif.gif]
[02:57:10] [1] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/middle/2014/08/gifbrewery/animation_gif.gif]
[02:57:10] [1] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb-2x/2014/08/gifbrewery/animation_gif.gif]
[02:57:15] [2] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb-2x/2014/06/start/thumbnail_960.png]
[02:57:49] [2] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/06/start/thumbnail_960.png]
[02:57:50] [2] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/middle/2014/06/start/thumbnail_960.png]
[02:57:54] [3] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/thumb-2x/2014/08/gifbrewery/capture_tool.png]
...
[03:25:40] gulp-imagemin: Minified 141 images (saved 2.29 MB - 12.2%)
[03:25:40] [141] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/middle/2014/11/high-performance-browser-networking-meetup/thumbnail.png]
[03:25:40] Found [141] files.
[03:25:40] Finished 'image-optim:middle' after 29 min
[03:25:40] [136] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/11/ios_byword_and_ver22/iphone_preview.png]
[03:25:42] [137] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/11/ios_byword_and_ver22/upload_success.png]
[03:26:19] [138] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/10/hello-yosemite/vmware_error.png]
[03:26:50] [139] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/10/hello-yosemite/thumbnail.png]
[03:27:03] [140] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/11/high-performance-browser-networking-meetup/thumbnail.png]
[03:27:28] gulp-imagemin: Minified 141 images (saved 11.44 MB - 34.9%)
[03:27:28] [141] [/Users/ryuichi/Projects/gulp.whiskers.nukos.kitchen/prd/uploads/origin/2014/11/ios_byword_and_ver22/ipad_preview.png]
[03:27:28] Found [141] files.
[03:27:28] Finished 'image-optim:origin' after 30 min
[03:27:28] Starting 'image-optim'...
[03:27:28] Finished 'image-optim' after 27 μs

すべてのタスクが完了するまで30分程度かかりました。オリジナルの画像が2000px以上の画像だったりするのでやはり時間がかかりました。初回はファイル量が多いため時間がかかってしまうのも仕方ありませんが、2回目以降は変更しれたファイルのみが対象となるためそれほど気にならなくなります。もう一度実行してみるとgulp-changedプラグインのおかげで一切の処理が実行されていません。

$ gulp image-optim
[03:35:07] Using gulpfile ~/Projects/gulp.whiskers.nukos.kitchen/gulpfile.js
[03:35:07] Starting 'image-optim:thumb'...
[03:35:07] Starting 'image-optim:thumb-2x'...
[03:35:07] Starting 'image-optim:middle'...
[03:35:07] Starting 'image-optim:origin'...
[03:35:07] gulp-imagemin: Minified 0 images (saved 0 B - 0%)
[03:35:07] Found [0] files.
[03:35:07] Finished 'image-optim:origin' after 375 ms
[03:35:07] gulp-imagemin: Minified 0 images (saved 0 B - 0%)
[03:35:07] Found [0] files.
[03:35:07] Finished 'image-optim:thumb-2x' after 383 ms
[03:35:07] gulp-imagemin: Minified 0 images (saved 0 B - 0%)
[03:35:07] Found [0] files.
[03:35:07] Finished 'image-optim:thumb' after 396 ms
[03:35:07] gulp-imagemin: Minified 0 images (saved 0 B - 0%)
[03:35:07] Found [0] files.
[03:35:07] Finished 'image-optim:middle' after 381 ms
[03:35:07] Starting 'image-optim'...
[03:35:07] Finished 'image-optim' after 8 μs

これで、PhotoshopやWebツールに頼らずともサムネイル画像や画像のリサイズ、軽量化を行えるようになりました。明日はSketch 3との連携について紹介していきたいと思います。

この記事はこれからはじめるGulp(16):gulp-image-resizeプラグインを使ってサムネイルやレスポンシブイメージを作るの転載です。