CSS+SVGタグで色弱シミュレーターみたいなのを作ってみる

SVGのfilterとfeColorMatrixを使うとHTML要素や画像を色変換することができます。これを利用して色弱シミュレーターみたいなのを作ってみようというお話です。

※ここでいう「色弱」という呼称は[CUDO（カラーユニバーサルデザイン機構）](http://www2.cudo.jp/wp/?page_id=84)の提唱する色覚の呼称となりますので、P型（protanopia）、D型（deuteranopia）、T型（tritanopia）、A型（Achromatopsia）の事を指しています。

## 実際に動くサンプルスクリプト
実際に動くサンプルとして以下のスクリプトを公開しています（テストコードなのでソースコードは美しくないです）。色の名前を教えてくれるアプリなんですが、今回の手法を使った色弱シミュレーション機能を搭載しています。

いろのなまえ - http://jsrun.it/hachisuka_nsw/iro-no-namae/

## 具体に記述の仕方は？
SVGタグのfilter要素は以下のように記述します。

```html
<filter id="protanopia">
  <feColorMatrix
    in="SourceGraphic"
    type="matrix"
    values="0.152286   1.052583 -0.204868 0 0
            0.114503   0.786281  0.099216 0 0
            -0.003882 -0.048116  1.051998 0 0
            0          0         0        1 0"/>
</filter>
```

この例の場合、変換後の色は以下のように変換されます。

```text
r' = r*0.152286  + g*1.052583  + b*-0.204868 + a*0 + 0
g' = r*0.114503  + g*0.786281  + b*0.099216, + a*0 + 0
b' = r*-0.003882 + g*-0.048116 + b*1.051998, + a*0 + 0
a' = r*0         + g*0         + b*0         + a*1 + 0
```

このフィルターを適用するにはCSSを使用します。以下の例は画像fruit.pngにフィルターをかけています。

```html
<img src="fruit.png" style="-webkit-filter: url('#protanopia'); filter: url('#protanopia');">
```
もちろんstyleタグでもいけますし、

```html
<style>
  img {-webkit-filter: url('#protanopia'); filter: url('#protanopia');}
</style>
```

画像だけでなくdivタグやbodyタグにも適用可能です。

## valuesの値は？
SVGタグのfilter要素とCSSで色変換が行えることは分かったのですが、実際に色変換を行うためにはvaluesの値がとても重要となります。

以下のサイトでそれらしいものを見つけましたので今回はそれを使用してみようと思います。このサイトにはA型（Achromatopsia）の値はありませんでしたので、今回はP型（protanopia）、D型（deuteranopia）、T型（tritanopia）の3つに絞る事としました。

http://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html

## 実際のHTML
実際のHTMLは以下のとおりです。画像fruit.pngを色弱シミュレーションするサンプルです。ブラウザで表示する前にfurit.pngの名前で画像を適当にダウンロードするか作成しておく必要があります。

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
      img {-webkit-filter: url('#protanopia'); filter: url('#protanopia');}
    </style>
</head>
<body>
<img src="fruit.png">
<svg
  xmlns="http://www.w3.org/2000/svg"
  version="1.1">
  <defs>
    <filter id="protanopia">
      <feColorMatrix
        in="SourceGraphic"
        type="matrix"
        values="0.152286   1.052583 -0.204868 0 0
                0.114503   0.786281  0.099216 0 0
                -0.003882 -0.048116  1.051998 0 0
                0          0         0        1 0"/>
    </filter>
    <filter id="deuteranopia">
      <feColorMatrix
        in="SourceGraphic"
        type="matrix"
        values="0.367322   0.860646 -0.227968 0 0
                0.280085   0.672501  0.047413 0 0
                -0.011820  0.042940  0.968881 0 0
                0          0         0        1 0"/>
    </filter>
    <filter id="tritanopia">
      <feColorMatrix
        in="SourceGraphic"
        type="matrix"
        values="1.255528  -0.076749 -0.178779 0 0
                -0.078411  0.930809  0.147602 0 0
                0.004733   0.691367  0.303900 0 0
                0          0         0        1 0"/>
    </filter>
  </defs>
</svg>
</body>
</html>
```

protanopia以外の色弱に変更するにはCSSの部分を、

```html:deuteranopia
img {-webkit-filter: url('#deuteranopia'); filter: url('#deuteranopia');}
```

や

```html:tritanopia
img {-webkit-filter: url('#tritanopia'); filter: url('#tritanopia');}
```

に変更することで適用できます。

また、`<style>`から`</style>`を削除して以下のように書けば比較することもできます。

```html
<img src="fruit.png"><br />
<img src="fruit.png" style="-webkit-filter: url('#protanopia'); filter: url('#protanopia');"><br />
<img src="fruit.png" style="-webkit-filter: url('#deuteranopia'); filter: url('#deuteranopia');"><br />
<img src="fruit.png" style="-webkit-filter: url('#tritanopia'); filter: url('#tritanopia');"><br />
```

## svgタグを外部ファイルにするには？
`<svg>`から`</svg>`を切り出してsvgファイルとして保存して読み込むこともできます。その場合、１行目に`<?xml>`のタグを入れてあげないとsvgファイルとして認識してくれませんので注意が必要です。

```text:filter.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
  xmlns="http://www.w3.org/2000/svg"
  version="1.1">
  <defs>
    <filter id="protanopia">
（省略）
```

保存したsvgファイルを適用するには以下のように書きます。#の前にファイル名を書くだけです。

```html:protanopia
img {-webkit-filter: url('filter.svg#protanopia'); filter: url('filter.svg#protanopia');}
```