Gruntで画像最適化

## 背景

* 画像最適化の際にGUIを使うのは面倒
* でもpngquantとかで都度コマンド実行するのも面倒
* Gruntでcssとかscriptとまとめてやりたい

## 結論
grunt-imageを使うのが良さそう
https://www.npmjs.org/package/grunt-image

* imageminと比較して最適化率にほぼ差がない
* これは私の環境だけかもしれないけど、imageminのpluginが動かないものがあったり、デフォルトでgif圧縮ができなかったり、バージョン落とすとgifは動くけどpngのpluginが〜とか、ちょっと不安定な感じがした

## 検証
### 1. grunt-pngmin
https://www.npmjs.org/package/grunt-pngmin

#### 最適化に使ってるもの
* pngquant

#### Gruntfile.jsへの記述
```
pngmin: {
　target1: {
　　options: {
　　　// pngquant実行のオプションをここに
　　　speed: 1,
　　　binary: 'pngquant',
　　　ext: '.png',
　　　force: true
　　},
　　files: [{
　　　// 圧縮対象のpathをここに
　　　src: "img/*",
　　　dest: "img/"
　　}]
　}
}
```
#### 実行結果
```
$ grunt pngmin
Running "pngmin:target1" (pngmin) task
Optimized {画像} [saved 51 % - 17.9 kB → 8.7 kB]
Overall savings: 51 % | 9.2 kB
Done, without errors.

Execution Time (2014-06-09 02:34:40 UTC)
loading tasks     7ms  ▇ 3%
pngmin:target1  224ms  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 96%
Total 234ms
```
* シンプル
* pngだけならこれで十分な気はする

### 2. grunt-imagemin
https://www.npmjs.org/package/grunt-contrib-imagemin

#### 最適化に使ってるもの
デフォルトは以下。ただしpluginで追加可能
* optiping
* gifsicle
* jpegtran
* svgo

#### Gruntfile.jsへの記述
```
imagemin: {
　// 特定の画像はこちら
　static: {
　　options: {
　　　optimizationLevel: 1,
　　　// ここで色々プラグインを指定できる
　　　use: [pngquant(), optipng(), pngout()]
　　},
　　files: {
　　　'img/HOGE.png': 'img/HOGE.png'
　　}
　},
　// まとめて
　dynamic: {
　　files: [{
　　　expand: true,
　　　cwd: 'img/',
　　　src: ['**/*.{png,jpg,gif}'],
　　　dest: 'img/'
　　}
　]}
}
```

#### 実行結果
```
$ grunt imagemin
Running "imagemin:static" (imagemin) task
✔ {画像} (saved 9.44 kB - 51%)
Minified 1 image (saved 9.44 kB)

Done, without errors.


Execution Time (2014-06-09 05:40:41 UTC)
loading tasks     77ms  ▇ 2%
imagemin:static   1.4s  ▇▇▇▇▇ 98%
Total 2s
```
* 使いたいプラグインを選べる  
https://www.npmjs.org/browse/keyword/imageminplugin  
けど、pngcrush・mozjpegが使えなかった
* jpegも対応している
* gifはコマンドエラーで使えなかったが、v0.5.0に入れ替えたら動いた、不思議 :laughing: 

### 3. grunt-image
https://www.npmjs.org/package/grunt-image

#### 最適化に使ってるもの
いっぱい！
* pngquant
* optipng
* advpng
* zopflipng
* pngcrush
* pngout
* jpegtran
* jpeg-recompress
* jpegoptim
* gifsicle

#### Gruntfile.jsへの記述
* imageminと一緒

```
image: {
　static: {
　　files: {
　　　'img/HOGE.png': 'img/HOGE.png'
　　}
　},
　dynamic: {
　　files: [{
　　　expand: true,
　　　cwd: 'img/',
　　　src: ['**/*.{png,jpg,gif}'],
　　　dest: 'img/'
　　}]
　}
}
```

#### 実行結果
```
$ grunt image
Running "image:dynamic" (image) task
✔ {画像} -> before=18.36 kB after=8.14 kB reduced=10.22 kB(55.7%)

Done, without errors.

Execution Time (2014-06-09 03:56:48 UTC)
image:dynamic  10.9s  ▇▇▇▇▇▇▇▇ 100%
Total 10.9s
```
* もともと色々なツールが含まれていてさくっとインストールして使える
* 比較的圧縮率が高い
* jpegやgifも圧縮できる
* オプションの指定方法がわからんーできないっぽい


### 4. grunt-imageoptim
https://www.npmjs.org/package/grunt-imageoptim

#### 最適化に使ってるもの
* ImageOptim
* ImageAlpha

#### Gruntfile.jsへの記述
```
imageoptim: {
　myTask: {
　　src: ['dist/img/apply.png']
　}
}
```

#### 実行結果
```
 grunt imageoptim
Running "imageoptim:myTask" (imageoptim) task
Running ImageOptim...
{画像} was: 18.360kb now: 18.360kb saving: 0kb (0%)
TOTAL was: 18.360kb now: 18.360kb saving: 0kb (0%)

Done, without errors.


Execution Time (2014-06-10 07:46:03 UTC)
imageoptim:myTask  15.4s  ▇▇▇▇▇▇▇▇ 100%
Total 15.5s
```
* ImageOptimが起動してうざい...

### 5. grunt-img
https://www.npmjs.org/package/grunt-img

#### 最適化に使ってるもの
* optipng
* jpegtran

#### Gruntfile.jsへの記述
```
img: {
　myTask: {
　　src: ['img/'],
　　dest: 'dist/'
　}
}
```

#### 実行結果
```
$ grunt img
Running "img:myTask" (img) task
Running optipng... {画像}
** Processing: {画像}
1092x221 pixels, 4x8 bits/pixel, RGB+alpha
Input IDAT size = 18303 bytes
Input file size = 18360 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 14720
                               
Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 14720

Output file: {画像}

Output IDAT size = 14720 bytes (3583 bytes decrease)
Output file size = 14777 bytes (3583 bytes = 19.52% decrease)


Done, without errors.


Execution Time (2014-06-10 08:04:32 UTC)
loading tasks   77ms  ▇ 15%
img:myTask     428ms  ▇▇▇▇▇ 84%
Total 507ms
```
* 圧縮率がいまいち