Closed kmiya-culti closed 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 でいいかなという気もして悩ましいです。
比較の為に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
たしかに処理速度が気になりますね。
思い付いたら実行で色指定の最大値を可変にしてみました。
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
サイズ的には、意図した通りかなぁ・・・
ついでにRGB各色で最大値を指定出来るようにしました。 http://nanno.dip.jp/softlib/man/rlogin/sixel.tar.gz
sixel -t -p 1024 -m 30,100,30 snake.jpg | wc -c 803636
のようにしてみるのも面白いですね。
次期RLoginの試作版に画像を右クリックでポップアップメニューに「画像のヒストグラムを表示する」を追加してみました。減色の実験を簡単に確認できるようになります。
http://nanno.dip.jp/softlib/rlogin/2.23.7/
sixel snake.jpg
sixel -m256 snake.jpg
@kmiya-culti パレットの種類3は一昨年の時点で
https://github.com/meh/cancer
がRGBAカラースペース用に拡張しているので、
(#\
RLoginも2.17.2から3で256色の拡張をしてましたから考えることは、同じですね・・・
2.23.6からSixelでアルファ値を扱えるようにしたので#n;3;R;G;B;AにしていますがAの意味が微妙なところです。0で透明にするのか不透明するか違うかもしれません。
現在までの思い付きを仕様にまとめてみました。
DECGCIの256色及びアルファ値の拡張
n : 0-1023(パレット最大値-1) r,g,b : 0-255 a : 0-255(0で透明、指定無しは255で不透明) 更なる拡張性が無い。すでに実装済み
DECGCIのnをパレット最大値以上の場合に色指定と見なす(パレットの初期化値として見える)
n : 0-1023(パレット最大値-1)互換部分 n : 1024+2^15/18/21/24(5/6/7/8x3) ビット数により10進数表記がかなり多くなる
Sixelの2/0-2/15部分に新しいコマンド%(仮)を追加して2^32値を?~までの6ビット文字で表す %n; n : ビット列(0000aa aaaaaa rrrrrr rrgggg ggggbb bbbbbb)を6ビット+'?'で表し上桁は省略 10進表記より文字数が減るが更なる拡張性が無い。
DECGCIの最大値を可変にして分解能を指定する
n : 1-65535(パレット最大値をデコーダに知らせるのも有り?) r,g,b,a : 1-65535(デフォルト100) 色分解能が論理値で指定出来るので拡張性が高い。実際の分解能は、デコーダーに依存できる。
新しい思い付きです、新コマンド"(?;?)"を追加してDECGCIの数値を6ビット文字で表す (n;r;g;b;a) n,r,g,b,a : 0=?, 63=~の文字で数値を表す。後方の値が0の場合省略 10進表記より文字数が減るが、互換性が悪い
今のところ4と5が拡張性が高いので良いと思いますが・・・
3.、5.は形式の面から反対です。 現行のSIXELは3/15 から 7/14がピクセルパターンを表すと思っていたので、フォーマットの基本理念において崩れている感があります。
4.も形式面ですが、#;9;255;255;255;255 がなぜパレットタイプ2(RGB)の最大値を決めるのかがわかりませんでした。 (パレットタイプ1(HLS)には影響しないのか、なぜ#コマンドを使うのか等)
また、これらの拡張に際して、なんらかの応答シーケンス(xtermのgraphics attributeのような)を用いた互換性確保をセットで考える必要があると思います。
忘れていました。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)
思い付きを仕様の変更です
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はアルファ値で省略可能
新コマンド"(?;?)"を追加してDECGCIの数値を6ビット文字で表す (n;r;g;b;a)
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の拡張が有効のような気がします。
DECCTRとの関連はどうなりますでしょうか?
6の場合には、関係しそうなイメージですね。(DECRQTSRでのレスポンスも同様) 4の場合は、Sixelの内での指定と見えるので関係しそうなイメージに感じません。
DECCTRを考慮するとDECGCIのPuを利用して最大値を指定するのが良いかもしれませんね。カラー指定時にのみ最大値を変更するイメージです。
RLoginの現在の実装では、Sixel/ReGISのカラーパレットとDECCTR、SGR、OSC4などのパレットと別に管理しています。本来なら共通だと思うのですがSixelの画像表示で文字色が変わるのが嫌なのとデフォルト色が大きく異なるのが理由です。したがってDECCTRまで波及するのは、意図しづらいです。
実験的に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
@kmiya-culti 文句ばかりですみませんが... 釈然としないのが、
また、1パラメータ目が省略された場合0番のレジスタを表す、等の動きの方が自然で、省略することに意味を持たせる、というのも異例の感があります。
拡張のマナー的な話なので、API設計の作法の話とかと似ていて、明確な言語化ができずつかみどころもないのですが、心の奥の方でひっかかるものがあるのです。
例ですが、
#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区切りで調節できるようになっても、 そもそもリニアではない色空間が欲しいとか際限の無い欲望が発生してきてエンコード側・デコード側共に疲弊し混乱も起きるので、 ユースケースに沿った有限個のプロファイルを決めて運用するのが私の好みです。
@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]が無難のような気がします・・・(最大値指定は、マニアックかなぁ・・・?)
そろそろまとめに入ろうかと思います。
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表現することを考えれば%????;の拡張は、有効のような気がします・・・