kmiya-culti / RLogin

RLoginは、Windows上で動作するターミナルソフトです
http://nanno.bf1.jp/softlib/man/rlogin/
MIT License
478 stars 17 forks source link

Sixelの色情報を拡張 #21

Closed kmiya-culti closed 6 years ago

kmiya-culti commented 6 years ago

Sixelの色情報を拡張する実験を行ってみました。 http://nanno.dip.jp/softlib/man/rlogin/sixel.tar.gz

現状の#n;2;100;100;100で表現して随時更新の場合 sixel -t -p 256 snake.jpg | wc -c 1872297 sixel -t -p 512 snake.jpg | wc -c 1746129 sixel -t -p 1024 snake.jpg | wc -c 1615765

パレット数を増やすとキャッシュの効果が上がります。

次に#n;3;255;255;255で表現して随時更新の場合 sixel -t -c -p 1024 snake.jpg | wc -c 2321678

100x100x100と255x255x255の色数の違いで減色されない分大きくなります。 (正確には101x101x101と256x256x256になるのかな)

次にr<<16+g<<8+b+1024で24ビット+1024を整数表記した場合 sixel -t -b -p 1024 snake.jpg | wc -c 1487402

255;255;255で表現するより1487402/2321678=0.640でした。

次に%????;で6bit*4=24bitでSixel表現した場合 sixel -t -a -p 1024 snake.jpg | wc -c 1163970

255;255;255で表現するより1163970/2321678=0.501でした。

Sixelのフォーマットから考えると無理に24ビットの色表現を実現するより現状の減色によりサイズ縮小のほうが使い道が高いように感じました・・・

sixel -p 256 snake.jpg | wc -c 341208

将来的にアルファ値を合わせてARGBとして32bit表現することを考えれば%????;の拡張は、有効のような気がします・・・

arakiken commented 6 years ago

私も,作業途中ですが,とりあえず今までのところで試した結果を貼り付けてみます。

まず,libsixelのsrc/tosixel.cを修正し,パレット番号1024-33791(0x400-0x83ff)の デフォルトカラーを、"パレット番号-1024"の15ビットRGB(0x0000-0x7fff、RGB 5ビットずつ) と見なして、パレット定義なしにSixel Graphicsのシーケンスを出力するようにしてみました。 http://mlterm.sf.net/tosixel.c.diff (#define RGB_555をコメントアウトすると,15ビット(RGB 5ビットずつ)ではなく 21ビット(RGB 7ビットずつ)で出力)

修正前のlibsixelで img2sixel -I -dnone images/snake.png した場合(パレット随時更新):674,791bytes 上記パッチを当てて img2sixel -I -dnone images/snake.png した場合:483,098bytes さらに,#define RGB_555をコメントアウトした場合:1,314,487bytes

1024番以降の色番号に対応するデフォルトのRGBを決めただけと考えれば, Sixelの色指定の仕様と互換性も高いですし,端末エミュレータ側でパース するコストも低いので,15ビット程度なら悪くないかなとは思います。

24ビットやalphaも含めた32ビットまで対応するとなると,新たに, %????拡張を導入した方がいいと思いますが,そこまでするならiterm2のOSC1337 でいいかなという気もして悩ましいです。

kmiya-culti commented 6 years ago

比較の為にlibsixelのパレットの16ビット化での結果を測定してみました。 https://github.com/saitoha/libsixel/tree/feature-16bit-palette

for n in 128 256 512 1024 2048 4096 8192 16384 32768; do time img2sixel -qfull -p $n snake.jpg | wc -c; done

128 269,525 0.261s 256 328,183 0.228s 512 393,202 0.291s 1024 483,431 0.481s 2048 637,003 0.867s 4096 785,097 1.624s 8192 945,540 3.207s 16384 1,207,553 7.159s 32768 1,567,117 17.830s

たしかに処理速度が気になりますね。

kmiya-culti commented 6 years ago

思い付いたら実行で色指定の最大値を可変にしてみました。

sixel -t -p 1024 -m 50 snake.jpg | wc -c 853806 sixel -t -p 1024 -m 100 snake.jpg | wc -c 1615765 sixel -t -p 1024 -m 150 snake.jpg | wc -c 2010154 sixel -t -p 1024 -m 200 snake.jpg | wc -c 2202083 sixel -t -p 1024 -m 255 snake.jpg | wc -c 2321678

サイズ的には、意図した通りかなぁ・・・

kmiya-culti commented 6 years ago

ついでにRGB各色で最大値を指定出来るようにしました。 http://nanno.dip.jp/softlib/man/rlogin/sixel.tar.gz

sixel -t -p 1024 -m 30,100,30 snake.jpg | wc -c 803636

のようにしてみるのも面白いですね。 snake3010030

kmiya-culti commented 6 years ago

次期RLoginの試作版に画像を右クリックでポップアップメニューに「画像のヒストグラムを表示する」を追加してみました。減色の実験を簡単に確認できるようになります。

http://nanno.dip.jp/softlib/rlogin/2.23.7/

sixel snake.jpg sn256

sixel -m256 snake.jpg snfull

saitoha commented 6 years ago

@kmiya-culti パレットの種類3は一昨年の時点で https://github.com/meh/cancer がRGBAカラースペース用に拡張しているので、 (#\;3;\;\;\;\, 各色0-255) 他のがいいですね

kmiya-culti commented 6 years ago

RLoginも2.17.2から3で256色の拡張をしてましたから考えることは、同じですね・・・

2.23.6からSixelでアルファ値を扱えるようにしたので#n;3;R;G;B;AにしていますがAの意味が微妙なところです。0で透明にするのか不透明するか違うかもしれません。

kmiya-culti commented 6 years ago

現在までの思い付きを仕様にまとめてみました。

  1. DECGCIの256色及びアルファ値の拡張

    n;3;r;g;b;a

    n : 0-1023(パレット最大値-1) r,g,b : 0-255 a : 0-255(0で透明、指定無しは255で不透明) 更なる拡張性が無い。すでに実装済み

  2. DECGCIのnをパレット最大値以上の場合に色指定と見なす(パレットの初期化値として見える)

    n

    n : 0-1023(パレット最大値-1)互換部分 n : 1024+2^15/18/21/24(5/6/7/8x3) ビット数により10進数表記がかなり多くなる

  3. Sixelの2/0-2/15部分に新しいコマンド%(仮)を追加して2^32値を?~までの6ビット文字で表す %n; n : ビット列(0000aa aaaaaa rrrrrr rrgggg ggggbb bbbbbb)を6ビット+'?'で表し上桁は省略 10進表記より文字数が減るが更なる拡張性が無い。

  4. DECGCIの最大値を可変にして分解能を指定する

    n;9;r;g;b;a

    n : 1-65535(パレット最大値をデコーダに知らせるのも有り?) r,g,b,a : 1-65535(デフォルト100) 色分解能が論理値で指定出来るので拡張性が高い。実際の分解能は、デコーダーに依存できる。

  5. 新しい思い付きです、新コマンド"(?;?)"を追加してDECGCIの数値を6ビット文字で表す (n;r;g;b;a) n,r,g,b,a : 0=?, 63=~の文字で数値を表す。後方の値が0の場合省略 10進表記より文字数が減るが、互換性が悪い

今のところ4と5が拡張性が高いので良いと思いますが・・・

saitoha commented 6 years ago
  1. はルールが複雑過ぎてちょっと自分が人に説明できる気がしないですね...
saitoha commented 6 years ago

3.、5.は形式の面から反対です。 現行のSIXELは3/15 から 7/14がピクセルパターンを表すと思っていたので、フォーマットの基本理念において崩れている感があります。

saitoha commented 6 years ago

4.も形式面ですが、#;9;255;255;255;255 がなぜパレットタイプ2(RGB)の最大値を決めるのかがわかりませんでした。 (パレットタイプ1(HLS)には影響しないのか、なぜ#コマンドを使うのか等)

saitoha commented 6 years ago

また、これらの拡張に際して、なんらかの応答シーケンス(xtermのgraphics attributeのような)を用いた互換性確保をセットで考える必要があると思います。

kmiya-culti commented 6 years ago

忘れていました。xtermで"CSI ? Pi; Pa; Pv S"によるSixel/ReGISのパレット数の設定がありますね。 これを拡張するとしたらPiパラメータでしょうか・・・HLS、RGBAの最大値を変更したいとしたら

CSI ? 2;3;Ph;Pl;Ps S -> HLS最大値(360;100;100) CSI ? 3;3;Pr;Pg;Pb;Pa S -> RGBA最大値(100;100;100;100)

という感じでしょうか?

追加:Pi=2,3は、使っていました・・・8,9にでも変更します

CSI ? 8;3;Ph;Pl;Ps S -> HLS最大値(360;100;100) CSI ? 9;3;Pr;Pg;Pb;Pa S -> RGBA最大値(100;100;100;100)

kmiya-culti commented 6 years ago

思い付きを仕様の変更です

  1. DECGCIの最大値を可変にして分解能を指定する %1;h;l;s h : 1-65535(360) l,s : 1-65535(100) %2;r;g;b;a r,g,b,a : 1-65535(100)aはアルファ値で省略可能

  2. 新コマンド"(?;?)"を追加してDECGCIの数値を6ビット文字で表す (n;r;g;b;a)

  3. xtermのgraphics attribute(CSI ? Pi; Pa; Pv S)を拡張して最大値を指定する CSI ? 8;Pa;Ph;Pl;Ps S Pa : 1/2/3/4(read/reset/set/max) Ph,Pl,Ps : 1-65535(360;100;100) CSI ? 9;Pa;Pr;Pg;Pb;Pv Pa : 1/2/3/4(read/reset/set/max) Pr,Pg,Pb,Pv : 1-65535(100)Pvはアルファ値で省略可能 ※試してみましたが、常に応答があるのが問題でした。

5の拡張を試しましたが、思ったよりサイズが小さくなりませんでした。逆に多くなる場合もありました。6の拡張は、エンコーダで応答を確認することが出来ますが、単純なcatなどで表示するとゴミが表示されます。今のところ4の拡張が有効のような気がします。

saitoha commented 6 years ago

DECCTRとの関連はどうなりますでしょうか?

kmiya-culti commented 6 years ago

6の場合には、関係しそうなイメージですね。(DECRQTSRでのレスポンスも同様) 4の場合は、Sixelの内での指定と見えるので関係しそうなイメージに感じません。

kmiya-culti commented 6 years ago

DECCTRを考慮するとDECGCIのPuを利用して最大値を指定するのが良いかもしれませんね。カラー指定時にのみ最大値を変更するイメージです。

  1. 新しい思い付きです。DECGCI/DECCTRの最大値を可変にして分解能を指定する DECGCI : #;9;Px;Py;Pz DECCTR : DSC 2$p ;9;Px;Py;Pz / ... ST Pu=9でHLS(360;100;100)およびRGB(100;100;100)の最大値を変更 ※シンプルに9だけでHLS/RGBの最大値を共通で変更にしました

RLoginの現在の実装では、Sixel/ReGISのカラーパレットとDECCTR、SGR、OSC4などのパレットと別に管理しています。本来なら共通だと思うのですがSixelの画像表示で文字色が変わるのが嫌なのとデフォルト色が大きく異なるのが理由です。したがってDECCTRまで波及するのは、意図しづらいです。

kmiya-culti commented 6 years ago

実験的に7の案を実装してみました。

http://nanno.dip.jp/softlib/man/rlogin/sixel.tar.gz http://nanno.dip.jp/softlib/rlogin/2.23.7/

xtetm-333に対するパッチです。 xterm-extcol.zip

saitoha commented 6 years ago

@kmiya-culti 文句ばかりですみませんが... 釈然としないのが、

;9;255;255;255;255

コマンドの2パラメータ目(ここに入るのは適切な方法で予約したカラースペース番号だと思っている)に9を入れると、なぜ特別な作用が発生するのか、という理屈です。

saitoha commented 6 years ago

また、1パラメータ目が省略された場合0番のレジスタを表す、等の動きの方が自然で、省略することに意味を持たせる、というのも異例の感があります。

saitoha commented 6 years ago

拡張のマナー的な話なので、API設計の作法の話とかと似ていて、明確な言語化ができずつかみどころもないのですが、心の奥の方でひっかかるものがあるのです。

saitoha commented 6 years ago

例ですが、

#1003 : 8bit RGB
#1004 : 9bit RGB
#1005 : 10bit RGB

等とすることで、形式上の新セマンティクスを導入することなく順当にカラースペースを増やしていけないでしょうか。 (カラースペースにオフセット1000を付加しているのは好みの問題で「DEC以後の実装による拡張」のニュアンスです) メリットとして下記のような「フォールバック表現」が可能になり、後方互換性の維持を期待できます。

#0;2;<R>;<G>;<B>
#0;1003;<R8>;<G8>;<B8>
#0;1005;<R10>;<G10>;<B10>

(0番のレジスタを 10bitカラースペース表現が利用可能であれば<R10>;<G10>;<B10>に、 8bitカラースペース表現が利用可能であれば<R8>;<G8>;<B8>に、 さもなくばDEC互換の<R>;<G>;<B>に設定する、という意味)

分解能を各色16bit区切りで調節できるようになっても、 そもそもリニアではない色空間が欲しいとか際限の無い欲望が発生してきてエンコード側・デコード側共に疲弊し混乱も起きるので、 ユースケースに沿った有限個のプロファイルを決めて運用するのが私の好みです。

kmiya-culti commented 6 years ago

@arakiken 文句ばかりが重要ですね!

ちょっと整理してDECGCIを"#Pc;Pu;Px;Py;Pz"と表現するとします。 Puがカラースペース(色空間)番号で考えると中途半端な9番は、無さそうですね。

Pu=1 : HLS(360;100;100)
Pu=2 : RGB(100;100;100)
...
Pu=4 : R4G4B4(15;15;15)
Pu=5 : R5G5B5(31;31;31)
Pu=6 : R6G6B6(63;63;63)
Pu=7 : R7G7B7(127;127;127)
Pu=8 : R8G8B8(255;255;255)
...
Pu=16: R16G16B16(65535;65535;65535)

のように4~16でビット長を表すのも自然かもしれません。Puにあまり大きな数値を使用するとサイズ的に肥大化するので良くないと思います(増やすとしたら+100でPu=104...116でしょうか)

僕のイメージでは、Pu=2,4-16は、RGBの最大値のみが変化しているのでそれを指定できればすべて表現できるのでそれを行うPuを設定したらと思い適当に9番にしましたが0番が空いていますね・・・思い付き仕様8です。

Pu=0 : MAX(1-65535;...)
Pu=1 : HLS(360;100;100)
Pu=2 : RGB(100;100;100)

実際に実装してみて思ったのがHLSとRGBでデフォルトの最大値が違うのが面倒ですがPx;Py;Pzの最大値を変数にするだけで思ったより簡単でした。問題点としては、HLS/RGBの混在で指定し直す必要があるのとパラメータが0の時に除算で使用するので違う意味を持たせる必要があることでした。

残念ながらxtermでは、Pu=1/2以外およびPx;Py;Pzが最大値を超えると処理を中断してしまいますが、最大値でクリップする実装では、それなりに表示が行えます(超えた場合は、白ぼけ、低い場合は、黒つぶれ)これは、長所・短所どちらとも取れます。

また、最大値指定時のPcですが、空白に意図がありません。どのような意味を持たせるか考えどころですが、無効かそのまカラーレジスタ番号指定でしょうか・・・

そもそもリニアではない色空間が欲しいとか際限の無い欲望が発生してきて

あはは・・・それも考えていました!ガンマ値を指定すれば、デコーダは逆数で戻す・・・あまりにもマニアックですね・・・

あまり欲張った仕様を設定するより現在の状況を改善する程度と考えれば思い付き仕様1のPu=3でR8;G8;B8[;A8]が無難のような気がします・・・(最大値指定は、マニアックかなぁ・・・?)

kmiya-culti commented 6 years ago

そろそろまとめに入ろうかと思います。

Sixelの色情報を拡張2