seq2gif icon indicating copy to clipboard operation
seq2gif copied to clipboard

Fix color biases

Open akinomyoga opened this issue 5 years ago • 3 comments

色が変質する問題が幾つかあるのでその修正です。

1. GIF colormap のオプション追加 9e5f1b7

問題点

現在の master の端末の配色は Solarized (for xterm-256color) です。現在の GIF 出力は左のようになりますが、実際の Solarized (for xterm-256color) は右のようになるべきです。

support-dither color16-master support-dither color16-xterm256-none

原因と解決法

色が変化していますが、これは GIF に出力する際に、GIF の256色カラーテーブルから近い色を拾うためです。具体的には、今 GIF のカラーテーブルは rgb332 (R 3bit, G 3bit, B 2bit) の色立方体で初期化されています。これが端末の256色カラーテーブル (Solarized 16色 + 6x6x6色立方体 + 24色グレースケール) と一致しないのが色の変化の原因です。

GIF のカラーテーブルをオプション -m, --colormap=MAP で切り替えられる様にしました。元々のテーブル -m rgb332 とし、コメントアウトされていた端末のテーブルをコピーする方を -m xterm256 としました。Sixel 等を使わない場合は基本的には端末の256色しか使われないので、既定の設定では端末の256色テーブルを用いるように変更しました。

2. 減色 (pixel2index) のバイアス補正 06c81d1 afa21a4

問題点

現在の master ですと全体的に画像の明るさが変化します。以下の表の左側が元の画像・アニメーションで右側が seq2gif で生成した GIF です。- 上段の画像は tests/data/sixel.tty を元にしています。全体に(特に顔色が)白くなっています (左の画像が白背景なのは単にそのような端末で撮っただけなのでその違いは無視して頂けると幸いです)。- 下段の画像は libsixel の snake.bmp を元にしています。こちらは逆に全体的に暗く・濃くなっています。

Original image seq2gif master
support-dither original support-dither master
support-dither snake support-dither snake-master

原因と解決法

masterpixel2index (rgb332) では以下の式(1)を用いて減色していますが、明るい色はより明るく、暗い色はより暗くなる様なバイアスがかかっています。図は量子化誤差 (= (減色後強度) - (減色前強度)) をグラフにした物です。06c81d1 で誤差がより均一な式(2)に変更します。

# (1) master
r = (r >> (8 - RED_MASK))   & bit_mask[RED_MASK];

# (2) This PR
r = (r * bit_mask[RED_MASK  ] + bit_mask[7]) / bit_mask[8];

support-dither bias1 support-dither bias2

afa21a4 で -m xterm256pixel2index の方も同様に修正しています。

support-dither bias3 support-dither bias4

(続き)

3. 誤差拡散 76ce6e6

それでも色が微妙に変わるので誤差拡散も実装しました。Floyd-Steinberg 法です。既定で有効にしていますが、既定のカラーテーブル -m xterm256 では、端末の256色以外の色を使わない限りは誤差拡散がない場合と同じ結果になります。

Original image -d none -d fs (誤差拡散)
-m rgb332 support-dither original support-dither rgb332-none support-dither rgb332-fs
-m xterm256 support-dither original support-dither xterm256-none support-dither xterm256-fs
Original image -d none -d fs (誤差拡散)
-m rgb332 support-dither snake support-dither snake-rgb332-none support-dither snake-rgb332-fs
-m xterm256 support-dither snake support-dither snake-xterm256-none support-dither snake-xterm256-fs

akinomyoga avatar Aug 24 '20 23:08 akinomyoga

Coverage Status

Coverage increased (+1.5%) to 65.888% when pulling 502d20380982252f5a7eeedf6ea43210067afe33 on akinomyoga:support-dither into 886138ed6a682273bc70fec0823ec14f9069ba67 on saitoha:master.

coveralls avatar Aug 25 '20 00:08 coveralls

This is another important fix that I believe should be merged at some point. Would like to hear opinions.

akinomyoga avatar Dec 03 '20 20:12 akinomyoga

I'm recently thinking that we should perform the error diffusion in the linear RGB space rather than in the sRGB space while keeping the nearest color pickup in the sRGB space. The current PR performs the error diffusion in the sRGB space.

akinomyoga avatar Aug 30 '21 14:08 akinomyoga