技ログ

Tech, etc.

OptiPNGでPNG形式の画像をロスレス圧縮・軽量化する

OptiPNGでPNG形式の画像を劣化なく圧縮し軽量化する。
OptiPNG公式

CentOSならyumでもインストール可能だが、バージョンが少し古いので、 ソースからインストールした。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ yum info optipng
Name        : optipng
Arch        : x86_64
Version     : 0.6.4
Release     : 1.el6
Size        : 82 k
Repo        : epel
Summary     : PNG optimizer and converter
URL         : http://optipng.sourceforge.net/
License     : zlib
Description : OptiPNG is a PNG optimizer that recompresses image files to a smaller size,
            : without losing any information. This program also converts external formats
            : (BMP, GIF, PNM and TIFF) to optimized PNG, and performs PNG integrity checks
            : and corrections.

ソースをダウンロード・展開。

1
2
3
$ wget "http://prdownloads.sourceforge.net/optipng/optipng-0.7.4.tar.gz?download"
$ tar xzf optipng-0.7.4.tar.gz
$ cd optipng-0.7.4

インストール方法確認。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[root@vagrant-blog optipng-0.7.4]# cat README.txt
Build instructions
------------------
  On Unix, or under a Bourne-compatible shell, run ./configure and make:
        cd optipng-0.7.4/
        ./configure
        make
        make test

Installation instructions
-------------------------
  Build the program according to the instructions above.

  On Unix:
  - Make the "install" target:
        sudo make install
  - To uninstall, make the "uninstall" target:
        sudo make uninstall

[root@vagrant-blog optipng-0.7.4]# ./configure --help
Usage:
    ./configure [options]
Options:
    -h, -help               Show this help
Installation directories:
    -prefix=PREFIX          Install architecture-independent files in PREFIX
                            [default: /usr/local]
    -exec-prefix=EPREFIX    Install architecture-dependent files in EPREFIX
                            [default: PREFIX]
    -bindir=DIR             Install executable in DIR [default: EPREFIX/bin]
    -mandir=DIR             Install manual in DIR [default: PREFIX/man]
Optional features:
    -enable-debug           Enable debug build flags and run-time checks
Optional packages:
    -with-system-libpng     Use the system-supplied libpng
                            [default: false]
    -with-system-zlib       Use the system-supplied zlib
                            [default: with-system-libpng]
Environment variables:
    CC                      C compiler command
    LD                      Linker command
    CFLAGS                  C compiler flags (e.g. -O3)
    CPPFLAGS                C preprocessor flags (e.g. -I DIR)
    LDFLAGS                 Linker flags (e.g. -L DIR)
    LIBS                    Additional libraries (e.g. -lfoo)

終了コードを確認しつつ、configure→make→make test→make installする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ./configure ; echo $?
0
$ CPU_CORE=$(grep -c '^processor\b' /proc/cpuinfo)
$ make -j $CPU_CORE ; echo $?
0
$ make test -j $CPU_CORE ; echo $?
0
$ sudo make install ; echo $?
cd src/optipng && \
  make install && \
  cd ../..
make[1]: Entering directory `/usr/local/src/optipng-0.7.4/src/optipng'
mkdir -p /usr/local/bin
mkdir -p /usr/local/man/man1
cp -f -p optipng /usr/local/bin
cp -f -p man/optipng.1 /usr/local/man/man1
make[1]: Leaving directory `/usr/local/src/optipng-0.7.4/src/optipng'
0

インストール確認。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ optipng -v
OptiPNG version 0.7.4
Copyright (C) 2001-2012 Cosmin Truta and the Contributing Authors.

This program is open-source software. See LICENSE for more details.

Portions of this software are based in part on the work of:
  Jean-loup Gailly and Mark Adler (zlib)
  Glenn Randers-Pehrson and the PNG Development Group (libpng)
  Miyasaka Masaru (BMP support)
  David Koblas (GIF support)

Using libpng version 1.4.12 and zlib version 1.2.7-optipng

オプション確認。
普通に使う分にはオプションなしでファイル指定するだけで圧縮してくれる。
→細かくオプションの内容を確認したい場合はman optipngする

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ optipng --help
Synopsis:
    optipng [options] files ...
Files:
    Image files of type: PNG, BMP, GIF, PNM or TIFF
Basic options:
    -?, -h, -help show this help
    -o <level>    optimization level (0-7)    [default: 2]
    -v      run in verbose mode / show copyright and version info
General options:
    -backup, -keep  keep a backup of the modified files
    -clobber    overwrite existing files
    -fix    enable error recovery
    -force    enforce writing of a new output file
    -preserve   preserve file attributes if possible
    -quiet, -silent run in quiet mode
    -simulate   run in simulation mode
    -out <file>   write output file to <file>
    -dir <directory>  write output file(s) to <directory>
    -log <file>   log messages to <file>
    --      stop option switch parsing
Optimization options:
    -f <filters>  PNG delta filters (0-5)     [default: 0,5]
    -i <type>   PNG interlace type (0-1)
    -zc <levels>  zlib compression levels (1-9)   [default: 9]
    -zm <levels>  zlib memory levels (1-9)    [default: 8]
    -zs <strategies>  zlib compression strategies (0-3) [default: 0-3]
    -zw <size>    zlib window size (256,512,1k,2k,4k,8k,16k,32k)
    -full   produce a full report on IDAT (might reduce speed)
    -nb     no bit depth reduction
    -nc     no color type reduction
    -np     no palette reduction
    -nx     no reductions
    -nz     no IDAT recoding
Editing options:
    -snip   cut one image out of multi-image or animation files
    -strip <objects>  strip metadata objects (e.g. "all")
Optimization levels:
    -o0   <=> -o1 -nx -nz       (0 or 1 trials)
    -o1   <=> -zc9 -zm8 -zs0 -f0      (1 trial)
        (or...) -zc9 -zm8 -zs1 -f5      (1 trial)
    -o2   <=> -zc9 -zm8 -zs0-3 -f0,5      (8 trials)
    -o3   <=> -zc9 -zm8-9 -zs0-3 -f0,5    (16 trials)
    -o4   <=> -zc9 -zm8 -zs0-3 -f0-5      (24 trials)
    -o5   <=> -zc9 -zm8-9 -zs0-3 -f0-5    (48 trials)
    -o6   <=> -zc1-9 -zm8 -zs0-3 -f0-5    (120 trials)
    -o7   <=> -zc1-9 -zm8-9 -zs0-3 -f0-5    (240 trials)
    -o7 -zm1-9  <=> -zc1-9 -zm1-9 -zs0-3 -f0-5    (1080 trials)
Notes:
    The combination for -o1 is chosen heuristically.
    Exhaustive combinations such as "-o7 -zm1-9" are not generally recommended.
Examples:
    optipng file.png            (default speed)
    optipng -o5 file.png          (slow)
    optipng -o7 file.png          (very slow)

ここでは360KBの画像を圧縮してみる。
まずは-simulateオプションでどの程度圧縮されるか確認。
※実際には処理は行われない

→100KB程度圧縮される模様

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# optipng -simulate virtualbox-error-1.png
** Processing: virtualbox-error-1.png
1024x711 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 3x8 bits/pixel, RGB
Input IDAT size = 365449 bytes
Input file size = 368428 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 262703

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

No output: simulation mode.

-backupオプションでバックアップファイルを作成しつつ、圧縮してみる。

  • 27.96%圧縮され、約100KB軽量化
  • 処理時間は2秒程度(MacBook Pro Retina Late 2013 Core i5のVirtualbox上の仮想マシン)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ optipng -backup virtualbox-error-1.png
** Processing: virtualbox-error-1.png
1024x711 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 3x8 bits/pixel, RGB
Input IDAT size = 365449 bytes
Input file size = 368428 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 262703

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

Output IDAT size = 262703 bytes (102746 bytes decrease)
Output file size = 265418 bytes (103010 bytes = 27.96% decrease)

$ ll virtualbox-error-1.png*
-rw-r--r--  1  501 501  265418 2014-01-28 23:15 virtualbox-error-1.png
-rw-r--r--  1  501 501  368428 2014-01-28 23:30 virtualbox-error-1.png.bak
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# time optipng -backup virtualbox-error-1.png
** Processing: virtualbox-error-1.png
1024x711 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 3x8 bits/pixel, RGB
Input IDAT size = 365449 bytes
Input file size = 368428 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 262703

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

Output IDAT size = 262703 bytes (102746 bytes decrease)
Output file size = 265418 bytes (103010 bytes = 27.96% decrease)


real  0m1.905s
user  0m1.900s
sys 0m0.003s
1
2
3
$ grep "model name" /proc/cpuinfo
model name  : Intel(R) Core(TM) i5-4288U CPU @ 2.60GHz
model name  : Intel(R) Core(TM) i5-4288U CPU @ 2.60GHz

Octopressで画像のwidth,height属性を指定する

Octopressで表示させる画像にwidth,height属性を指定するようにした。
http://octopress.org/docs/plugins/image-tag/

Syntax

1
{% img [class names] /path/to/image [width] [height] [title property [alt property]] %}

例えば、下記のように記述する。

1
2
-![alt property](/images/image-1.png)
+{% img /images/image-1.png 200 160 "title property" "alt property" %}

結果、生成されるHTMLは以下のようになる。

1
2
-<p><img src="/images/image-1.png" alt="alt property" /></p>
+<p><img src="/images/image-1.png" width="200" height="160" title="title property" alt="alt property"></p>

Octopressの言語指定を日本語にする

Octopressの言語指定はデフォルトで英語になっているため、 日本語の記事を書いていても、Chromeでアクセスすると英語サイト判定されて翻訳するかどうかの通知が出てしまう。

→source/_includes/head.html でlang属性を修正すれば良い

1
2
3
$ vim source/_includes/head.html
-<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
+<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="ja"><!--<![endif]-->

Octopressで日本語の記事が書けない

Octopressで一つ記事を書いたので、 試しにアップしようとしたところ、以下のエラーが出てgenerate出来ない。

※OSはCentOS 6.5で必要最小限のパッケージしか入れていない。
https://github.com/2creatives/vagrant-centos/releases/download/v6.5.1/centos65-x86_64-20131205.box

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ bundle exec rake generate
## Generating Site with Jekyll
identical source/stylesheets/screen.css
---
Configuration from /app/rails_projects/blog/rasaka.github.io/_config.yml
Building site: source -> public
YAML Exception reading 2014-01-13-nfs-mount-error.markdown: invalid byte sequence in US-ASCII
/app/rails_projects/blog/rasaka.github.io/plugins/backtick_code_block.rb:13:in `gsub': invalid byte sequence in US-ASCII (ArgumentError)
  from /app/rails_projects/blog/rasaka.github.io/plugins/backtick_code_block.rb:13:in `render_code_block'
  from /app/rails_projects/blog/rasaka.github.io/plugins/octopress_filters.rb:12:in `pre_filter'
  from /app/rails_projects/blog/rasaka.github.io/plugins/octopress_filters.rb:28:in `pre_render'
  from /app/rails_projects/blog/rasaka.github.io/plugins/post_filters.rb:112:in `block in pre_render'
  from /app/rails_projects/blog/rasaka.github.io/plugins/post_filters.rb:111:in `each'
  from /app/rails_projects/blog/rasaka.github.io/plugins/post_filters.rb:111:in `pre_render'
  from /app/rails_projects/blog/rasaka.github.io/plugins/post_filters.rb:166:in `do_layout'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/gems/jekyll-0.12.1/lib/jekyll/post.rb:195:in `render'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/gems/jekyll-0.12.1/lib/jekyll/site.rb:200:in `block in render'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/gems/jekyll-0.12.1/lib/jekyll/site.rb:199:in `each'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/gems/jekyll-0.12.1/lib/jekyll/site.rb:199:in `render'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/gems/jekyll-0.12.1/lib/jekyll/site.rb:41:in `process'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/gems/jekyll-0.12.1/bin/jekyll:264:in `<top (required)>'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/bin/jekyll:23:in `load'
  from /home/vagrant/.rbenv/versions/2.1.0/gemsets/blog-octopress/bin/jekyll:23:in `<main>'

現状のロケールを確認。

1
2
3
4
5
6
7
8
9
10
$ locale -a
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_COLLATE to default locale: No such file or directory
C
POSIX
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8

ja_JP.utf8を利用出来るようにする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ sudo localedef -f UTF-8 -i ja_JP ja_JP.utf8
$ locale -a
C
POSIX
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8
ja_JP.utf8
$ locale
LANG=ja_JP.utf8
LC_CTYPE="ja_JP.utf8"
LC_NUMERIC="ja_JP.utf8"
LC_TIME="ja_JP.utf8"
LC_COLLATE="ja_JP.utf8"
LC_MONETARY="ja_JP.utf8"
LC_MESSAGES="ja_JP.utf8"
LC_PAPER="ja_JP.utf8"
LC_NAME="ja_JP.utf8"
LC_ADDRESS="ja_JP.utf8"
LC_TELEPHONE="ja_JP.utf8"
LC_MEASUREMENT="ja_JP.utf8"
LC_IDENTIFICATION="ja_JP.utf8"
LC_ALL=

/etc/sysconfig/i18nを修正。

1
2
3
$ vim /etc/sysconfig/i18n
-LANG="en_US.UTF-8"
+LANG="ja_JP.utf8"

/etc/sysconfig/i18nを再読み込みで解決。

1
$ . /etc/sysconfig/i18n

Vagrant packageで複製したboxのSSHレスポンスが遅い

構築済みのVagrant boxをvagrant packageで複製し、 IPだけ変更して起動したところ、eth1が起動しなかった。

加えて、問題対処後に起動するも、SSHのレスポンスが遅かった。

box複製

1
2
3
Mac$ vagrant package
Mac$ vagrant box add copy_box package.box
Mac$ rm package.box

複製元のVagrantfileからIPだけ変更して起動。

1
2
-  config.vm.network :private_network, ip: "192.168.33.11"
+  config.vm.network :private_network, ip: "192.168.33.12"
1
Mac$ vagrant up

eth1が起動しない

起動時にeth1が存在しないとのエラーが発生。

1
2
3
4
5
6
7
8
9
10
11
12
[default] Configuring and enabling network interfaces...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

ARPCHECK=no /sbin/ifup eth1 2> /dev/null

Stdout from the command:

Device eth1 does not seem to be present, delaying initialization.


Stderr from the command:

下記を削除してからvagrant packageをやり直す。
https://github.com/mitchellh/vagrant/issues/1777

1
Vagrant$ rm /etc/udev/rules.d/70-persistent-net.rules
1
2
3
4
5
6
Mac$ vagrant destroy
Mac$ vagrant package
Mac$ vagrant box remove copy_box
Mac$ vagrant box add copy_box package.box
Mac$ rm package.box
Mac$ vagrant up

eth1が起動出来た。

1
2
3
4
5
6
7
8
9
10
$ ifconfig eth1
eth1      Link encap:Ethernet  HWaddr 00:00:00:00:00:00
          inet addr:192.168.33.12  Bcast:192.168.33.255  Mask:255.255.255.0
$ ping 192.168.33.1 -c 1
PING 192.168.33.1 (192.168.33.1) 56(84) bytes of data.
64 bytes from 192.168.33.1: icmp_seq=1 ttl=64 time=0.179 ms

--- 192.168.33.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.179/0.179/0.179/0.000 ms

SSHレスポンスが遅い

ただし、SSHのレスポンスが遅い。キーを押下しても一瞬待ってから表示される。
→google TOPへcurlしてみたが、通常と変わらない。
→ネットワーク自体は遅くない

Virtualboxで該当仮想マシンの設定を確認すると、下記のエラーが発生していた。

Virtualbox error screenshot

→VagrantfileでI/O APIC有効化設定。

1
2
3
4
5
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "1024"]
    vb.customize ["modifyvm", :id, "--cpus", 2]
+   vb.customize ["modifyvm", :id, "--ioapic", "on"]
  end

vagrant reloadで再起動→SSHのレスポンスが通常通りとなった。

1
Mac$ vagrant reload

VagrantでNFSマウント出来ない

ホストとの共有は NFSの方がパフォーマンスが良い らしいので、
Vagrantfileで設定してみたところ、エラーが発生してNFSマウント出来ない。

※追記あり(2014/1/23)

1
2
Mac$ vim Vagrantfile
config.vm.synced_folder "/Users/xxx/app/", "/app/", nfs: true

下記エラーが発生。

1
2
3
4
5
6
7
Mac$ vagrant up
[default] Exporting NFS shared folders...
NFS is reporting that your exports file is invalid. Vagrant does
this check before making any changes to the file. Please correct
the issues below and execute "vagrant reload":

Can't open /etc/exports

ホスト側で/etc/exportsを作成(空ファイルでよい)

1
Mac$ sudo touch /etc/exports

NFSは起動していた。

1
2
3
Mac$ sudo nfsd status
nfsd service is enabled
nfsd is running (pid 3697, 8 threads)

起動していなかった場合は以下を実行。

1
Mac$ sudo nfsd enable

別エラー発生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Mac$ vagrant reload
[default] Exporting NFS shared folders...
Preparing to edit /etc/exports. Administrator privileges will be required...
[default] Mounting NFS shared folders...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

mount -o 'vers=3,udp' 192.168.33.1:'/Users/xxx/app' /app

Stdout from the command:



Stderr from the command:

mount.nfs: access denied by server while mounting 192.168.33.1:/Users/xxx/app

sudo nfsd checkexports→vagrant reloadで解決
https://github.com/mitchellh/vagrant/issues/1744

1
2
3
4
5
Mac$ sudo nfsd checkexports
Mac$ vagrant reload
[default] Exporting NFS shared folders...
Preparing to edit /etc/exports. Administrator privileges will be required...
[default] Mounting NFS shared folders...

起動後、マウント出来ていることを確認。

1
2
3
Vagrant$ df -h /app
Filesystem                     Size  Used Avail Use% Mounted on
192.168.33.1:/Users/xxx/app  466G   48G  417G  11% /app

追記(2014/1/23)

OS再起動時に再発。

Mac OS側の/etc/exportsを確認してみると、Vagrantが自動生成している許可設定内のIP(10.0.2.15)と Vagrant up時に実行されているmountコマンドでのNFSサーバIP(192.168.33.1)とでネットワークが異なっている。

許可していないのだからdenyしますよね…。

1
2
3
4
Mac$ cat /etc/exports
# VAGRANT-BEGIN: 
"/Users/xxx/app" 10.0.2.15 -alldirs -mapall=501:20
# VAGRANT-END: 
1
2
3
4
5
6
7
8
9
10
11
12
13
[default] Mounting NFS shared folders...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

mount -o 'vers=3,udp' 192.168.33.1:'/Users/xxx/app' /app

Stdout from the command:



Stderr from the command:

mount.nfs: access denied by server while mounting 192.168.33.1:/Users/xxx/app

とりあえず、Mac OS側で/etc/exportsを手動変更。
→仮想マシン側の192.168.33.0/24のIPを許可

1
2
Mac$ sudo vim /etc/exports
+ "/Users/xxx/app" 192.168.33.12 -alldirs -mapall=501:20

手動でmountコマンド実行。
→マウント出来た。

ただ、これだと格好悪いので、Vagrantfileで綺麗に指定出来ないものだろうか。

1
2
3
4
Vagrant$ sudo mount -o 'vers=3,udp' 192.168.33.1:'/Users/xxx/app' /app
Vagrant$ df /app
Filesystem                    1K-blocks     Used Available Use% Mounted on
192.168.33.1:/Users/xxx/app 487712928 49724160 437732768  11% /app

バージョン

1
2
3
4
5
6
7
8
9
Mac$ vagrant --version
Vagrant 1.4.1
Mac$ sw_vers
ProductName:  Mac OS X
ProductVersion: 10.9.1
BuildVersion: 13B3116

Vagrant$ cat /etc/redhat-release
CentOS release 6.5 (Final)

VagrantのBox

https://github.com/2creatives/vagrant-centos/releases/download/v6.5.1/centos65-x86_64-20131205.box