ImageMagickで画像を座標＋RGB値のテキストに変換する、またその逆

ImageMagickコマンドで画像ファイルを「座標＋RGB値」のテキストに変換、またその逆もできる事を知ったのでその時のメモです。

これを使うメリットとしては、GDライブラリやRmagick、nodejsのcanvasパッケージといったライブラリをインストールしたり準備したりしなくても良いところと、簡単な画像処理ならテキスト処理するプログラムできてしまうところでしょうか。

##環境
試したのはLubuntu16.04です。LubuntuはOSをインストールしただけでデフォルトでImageMagickがインストールされますので、それをそのまま使っています。<2018/7/11追記>改めてみてみたらImageMagickはデフォルトではインストールされていませんでした。 `sudo apt install imagemagick` でインストールする必要があります。

```console:
$ convert -version
Version: ImageMagick 6.8.9-9 Q16 x86_64 2017-05-26 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules OpenMP
Delegates: bzlib cairo djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png rsvg tiff wmf x xml zlib
```

##画像をテキストに変換
画像ファイルをテキストファイルに変換するように書くだけで座標とカラー値のテキストに変換できます。

```console:カラー値に変換
$ convert test.png test.txt
```

###変換後のファイルの中身は？
変換されたファイルの中身は以下のような感じになります。見るとなんとなく分かるんですが、2行め以降に`X座標,Y座標: (R,G,B) ...`という形式で保存されている事が確認できると思います。

```console:テキストファイルの中身
$ cat test.txt
# ImageMagick pixel enumeration: 360,32,255,srgb
0,0: (255,1,1)  #FF0101  srgb(255,1,1)
1,0: (255,7,1)  #FF0701  srgb(255,7,1)
2,0: (255,7,1)  #FF0701  srgb(255,7,1)
3,0: (255,13,1)  #FF0D01  srgb(255,13,1)
4,0: (255,19,1)  #FF1301  srgb(255,19,1)
5,0: (255,25,1)  #FF1901  srgb(255,25,1)
6,0: (255,25,1)  #FF1901  srgb(255,25,1)
7,0: (255,31,1)  #FF1F01  srgb(255,31,1)
8,0: (255,37,1)  #FF2501  srgb(255,37,1)
（以下省略）
```

###ファイルではなく標準出力に書き出す
ファイルに書き出さずに標準出力したい時は以下のようにします。この方法を使うと一時ファイルを作ることなくプログラムで処理することができます。例）`f = open('|convert test.png txt:', 'r')`

```console:RGB値に変換
$ convert test.png txt:
```

###CMYKで取り出す
`-colorspace`でカラースペースで変換することもできますので、以下のようにすればRGBではなくCMYKに変換した結果を取り出すことができます。

```console:CMYK値に変換
$ convert test.png -colorspace CMYK txt:
# ImageMagick pixel enumeration: 360,32,255,cmyk
0,0: (0,254,254,0)  #00FEFE00  cmyk(0,254,254,0)
1,0: (0,248,254,0)  #00F8FE00  cmyk(0,248,254,0)
2,0: (0,248,254,0)  #00F8FE00  cmyk(0,248,254,0)
3,0: (0,242,254,0)  #00F2FE00  cmyk(0,242,254,0)
4,0: (0,236,254,0)  #00ECFE00  cmyk(0,236,254,0)
5,0: (0,230,254,0)  #00E6FE00  cmyk(0,230,254,0)
6,0: (0,230,254,0)  #00E6FE00  cmyk(0,230,254,0)
7,0: (0,224,254,0)  #00E0FE00  cmyk(0,224,254,0)
8,0: (0,218,254,0)  #00DAFE00  cmyk(0,218,254,0)
（以下省略）
```

###必要なところだけ切り出す
`-crop`を使えば一部だけ取り出すこともできます。以下の例は（9,0）から2x2だけ取り出します。

```console:(9,0)から2x2取り出す
$ convert color.png -crop 2x2+9+0 txt:
# ImageMagick pixel enumeration: 2,2,255,srgb
0,0: (255,37,1)  #FF2501  srgb(255,37,1)
1,0: (255,43,1)  #FF2B01  srgb(255,43,1)
0,1: (255,37,1)  #FF2501  srgb(255,37,1)
1,1: (255,43,1)  #FF2B01  srgb(255,43,1)
```

##テキストから画像に変換
今度は逆の座標とカラー値の書かれたテキストファイルを画像への変換を行ってみます。これも使い方は簡単でテキストファイルを画像ファイルへと変換するように書くだけです。

```console:テキストファイル（RGB値）から画像に変換
$ convert test2.txt test2.png
```

###テキストファイルの書き方
元となるテキストファイルは以下のような感じで書きます。1行目は注釈ですが必須となり`# ImageMagick pixel enumeration: `の後の`256,256,255,srgb`で横の長さ、縦の長さ、色数、カラースペースを指定します。

```console:テキストファイルの中身
$ cat test2.txt
# ImageMagick pixel enumeration: 256,256,255,srgb
0,0: (0,0,0)
1,0: (0,0,0)
2,0: (1,0,0)
3,0: (1,0,0)
4,0: (1,0,0)
5,0: (1,0,0)
6,0: (2,0,0)
7,0: (2,0,0)
8,0: (2,0,0)
（以下省略）
```

###標準入力からもOK
標準入力から変換することもできます。

```console:標準入力から変換
$ cat test2.txt | convert txt: test2.png
```

###カラーサンプルを描画してみる
この方法を使えばプログラムで画像ファイルを生成するといったこともできます。試しに以下のようなカラーサンプルを作るプログラムを書いてみました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/128670/c96bb5aa-2303-63cf-0e25-7e111ea68556.png)

このサンプルは色相(Hue)0度から359度まで描いているだけのものです。簡単なサンプルなんですが、これをRGBで描こうとすると色相をRGBに変換する必要があったりしてちょい面倒な話となります。しかしImageMagickならカラースペースにHSVやHSL等が指定できるため、比較的簡単に作成することができます。

```rb:カラーサンプル作成(Ruby)
f = open("|convert txt: color.png", "w")
f.puts "# ImageMagick pixel enumeration: 360,32,255,hsl"
(0...360).each do |x|
    (0...32).each do |y|
        f.puts "#{x},#{y}: (#{x*100.0/360}%,100%,50%)"
    end
end
f.close
```

Ruby じゃなくて bash + awk を使うなら以下のような感じかな。

```bash:カラーサンプル作成(bash+awk)
seq 0 359 | awk 'BEGIN{print "# ImageMagick pixel enumeration: 360,32,255,hsl"}{for(y=0; y<32; y++) printf("%d,%d: (%4.1f%%,100%%,50%%)\n", $1,y,$1*100/360)}' |  convert txt: color.png
```

##おまけ
ImageMagickでサポートされているカラースペースの一覧を取得する

```console:サポートされているカラースペースの一覧
$ convert -list colorspace
CIELab
CMY
CMYK
Gray
HCL
HCLp
HSB
HSI
（以下省略）
```

ImageMagickでサポートされているファイルフォーマットの一覧を取得する

```console:サポートされているファイルフォーマットの一覧
$ convert -list format
   Format  Module    Mode  Description
-------------------------------------------------------------------------------
      3FR  DNG       r--   Hasselblad CFV/H3D39II
      AAI* AAI       rw+   AAI Dune image
       AI  PDF       rw-   Adobe Illustrator CS2
      ART* ART       rw-   PFS: 1st Publisher Clip Art
      ARW  DNG       r--   Sony Alpha Raw Image Format
      AVI  MPEG      r--   Microsoft Audio/Visual Interleaved
      AVS* AVS       rw+   AVS X image
      BGR* BGR       rw+   Raw blue, green, and red samples
（以下省略）
```

画像ファイルの情報を得る

```console:画像ファイルの情報を得る
$ convert test.png info:
test.png PNG 360x32 360x32+0+0 8-bit sRGB 869B 0.000u 0:00.050
```