自然画モード YJK

MSX2+ で追加されている
最大 19268 色の自然画モード(SCREEN 10~12)について記載しています。

色コードとして YJK を使用します。
主に明度を表現する Y と色相を表現する J・K に分かれています。


YJK と RGB の変換

ここでの YJK は SCREEN 12 向けの値です。(Y=0~31・J/K=-32~31)
RGB はそれぞれ 0~31 となります。
31 を超える場合は 31、0 より少ない場合は 0 となります。

 

YJK→RGB

R=Y+J

G=Y+K

B=1¼Y-½J-¼K ※

 

※ MSX 関連書籍では 1¼Y の代わりに
  5/4 Y の記載です。 

 

分数の分母を 4 で統一すると……

 

R=Y+J

G=Y+K

B=(5Y-2J-K)×¼

 

RGB→YJK

Y=½B+¼R+⅛G

J=R-Y

K=G-Y

 

RGB の値に統一すると……

 

Y=¼R+⅛G+½B

J=¾R-⅛G-½B

K=-¼R+⅞G-½B

 

それぞれ分数の分母を 8 で統一すると……

 

Y=(2R+G+4B)×⅛

J=(6R-G-4B)×⅛

K=(-2R+7G-4B)×⅛

 


公式だと分かりづらいのですが、
×¼ は 2 ビット右シフト、×⅛ は 3 ビット右シフト です。

したがって、ビットの値から加算・減算・シフトの演算で
容易に変換できる仕組みになっています。

また Y の値を入れる際は ×8 で入るため、
2R+G+4B の計算結果から上位 5 ビットを維持できます。
(SCREEN 10・11 であれば上位 4 ビットを維持になり、
 実際の Y 値は 0~15 になります)

 

公式から得られる RGB→YJK の範囲は
Y≒0~27、J≒-19~23、K≒-23~27 となり、

一部の値は実際には使っていない事がわかります。
このページではこの範囲を考慮します。

 

小数は切り捨てよりも四捨五入するのが近い画質になるようです。
ビットでの四捨五入は、最後にあふれたビットを値に加えます。
このページで変換した値はすべて小数点以下を四捨五入した整数の値です。

ソフトによっては切り捨てで計算している可能性があり、
その場合は一部の値が異なってきます。


YJK による表示・RGB の値

画像は MSX エミュレータで実際に表示したもの(プログラム 参照)を
加工しています。

横が J の値(左が-、右が+)、縦が K の値(上が-、下が+)です。

※ YJK の説明をしている他所では
  K の値を上下逆(下が-、上が+)で掲載している場合があります。


合わせて上の公式を用いた YJK からの RGB 値も記載します。

ここでの RGB はそれぞれ 0~31 の値です。
すべて 0 なら黒、31 なら白になります。

 

ここでは RGB→YJK 変換の公式による範囲
Y=0~27、J=-19~23、K=-23~27 にしています。

YJK→RGB 変換時の小数以下は四捨五入です。

 

SCREEN 12 Y=0 の場合

J K RGB
 -19 -23 (0,0,15) 濃い青
-23 (0,0,6)
+23 -23 (23,0,0)

-19

(0,0,10) 濃い青
(0,0,0)
+23 (23,0,0)
-19 +27 (0,27,3)
+27 (0,27,0)
+23 +27 (23,27,0) 黄緑

 

特に黒(RGB=000)、赤(RGB=100)、緑(RGB=010)が表示されます。

いずれも B の値が半分以下でほとんどでてこない状態になっています。
赤・緑は範囲が長く、YJK→RGB 変換の範囲外を含めると
重複している部分も多くなっています。

 

SCREEN 12 Y=14 の場合

J K RGB
 -19 -23 (0,0,31)
-23 (14,0,23)
+23 -32 (31,0,12)
-19 (0,14,27) 薄い青
(14,14,18) 灰色
+23 (31,23,4) オレンジ
-19 +27 (0,31,20) 水色
+27 (14,31,11)
+23 +27 (31,31,1) 黄色

 

Y が中間になるとすべての色が混じり合うようになりますが、

特に青(RGB=001)と黄色(RGB=110)が表示されます。

J・K=0 の場合は青が濃い(=B の値が大きい)灰色になっている事がわかります。

 

SCREEN 12 Y=27 の場合

J K RGB
 -19 -23 (8,4,31)
-23 (27,4,31)
+23 -23 (31,4,28)
-19 (8,27,31) 水色
(27,27,31)
+23 (31,27,22) 薄い黄色
-19 +27 (8,31,31) 水色
+27 (27,31,27)
+23 +27 (31,31,16) 黄色

 

特に紫(RGB=101)、水色(RGB=011)、白(RGB=111)が表示されます。

いずれも B の値が半分以上含まれた色です。

 

ここから、J の値は主に赤(R)、K の値は主に緑(G)の
影響がある値である事が分かります。

一方青(B)は J・K がマイナスの値で現れ、更に Y の値でも影響を受けます。


黒~灰色~白の YJK 値

上の表より、Y=14・J=0・K=0 の場合 RGB が (14,14,18)、

Y=28・J=0・K=0 の場合 RGB が (27,27,31) と

J=0・K=0 では青(B)の値が大きくなっている事が分かります。

純粋な黒~灰色~白になる値はどこにあるのでしょうか?

 

そこで、灰色が存在する縦 Y の値と横 J・K の値を RGB に変換してみました。

縦が Y、横が J・K の値です。

RGB が一致していれば完全な 黒~灰色~白 となります。
ここでは黄色で強調しています。

Y の値が大きくなるほど、灰色に該当する J・K の値が
プラスへ動いているのが分かります。

 

RGB→YJK の変換上、Y=27 までが実際に使われている値です。
それ以上は計算上 (31,31,31) の範囲が大きくなっていきますが、
これらは変換の公式から得られる範囲として使われていません。
この範囲は色を変えています。

 

-1 0 1 2 3 4 5
0 (0,0,1) (0,0,0) (1,1,1) (2,2,0) (3,3,0) (4,4,0) (5,5,0)
1 (0,0,2) (1,1,1) (2,2,1) (3,3,0) (4,4,0) (5,5,0) (6,6,0)
2 (1,1,3) (2,2,3) (3,3,2) (4,4,1) (5,5,0) (6,6,1) (7,7,0)
3 (2,2,5) (3,3,4) (4,4,3) (5,5,2) (6,6,2) (7,7,1) (8,8,0)
4 (3,3,6) (4,4,5) (5,5,4) (6,6,4) (7,7,3) (8,8,2) (9,9,1)
5 (4,4,7) (5,5,6) (6,6,6) (7,7,5) (8,8,4) (9,9,3) (10,10,3)
6 (5,5,8) (6,6,8) (7,7,7) (8,8,6) (9,9,5) (10,10,5) (11,11,4)
7 (6,6,10) (7,7,9) (8,8,8) (9,9,7) (10,10,7) (11,11,6) (12,12,5)
8 (7,7,11) (8,8,10) (9,9,9) (10,10,9) (11,11,8) (12,12,7) (13,13,6)
9 (8,8,12) (9,9,11) (10,10,11) (11,11,10) (12,12,9) (13,13,8) (14,14,8)
10 (9,9,13) (10,10,13) (11,11,12) (12,12,11) (13,13,10) (14,14,10) (15,15,9)
11 (10,10,15) (11,11,14) (12,12,13) (13,13,12) (14,14,12) (15,15,11) (16,16,10)
12 (11,11,16) (12,12,15) (13,13,14) (14,14,14) (15,15,13) (16,16,12) (17,17,11)
13 (12,12,17) ((13,13,16) (14,14,16) (15,15,15) (16,16,14) (17,17,13) (18,18,13)
14 (13,13,18) (14,14,18) (15,15,17) (16,16,16) (17,17,15) (18,18,15) (19,19,11)
15 (14,14,20) (15,15,19) (16,16,18) (17,17,17) (18,18,17) (19,19,16) (20,20,15)
16 (15,15,21) (16,16,20) (17,17,19) (18,18,19) (19,19,18) (20,20,17) (21,21,16)
17 (16,16,22) (17,17,21) (18,18,21) (19,19,20) (20,20,19) (21,21,18) (22,22,18)
18 (17,17,23) (18,18,23) (19,19,22) (20,20,21) (21,21,20) (22,22,20) (23,23,19)
19 (18,18,25) (19,19,24) (20,20,23) (21,21,22) (22,22,22) (23,23,21) (24,24,20)
20 (19,19,26) (20,20,25) (21,21,24) (22,22,24) (23,23,23) (24,24,22) (25,25,21)
21 (20,20,27) (21,21,26) (22,22,26) (23,23,25) (24,24,24) (25,25,23) (26,26,23)
22 (21,21,28) (22,22,28) (23,23,27) (24,24,26) (25,25,25) (26,26,25) (27,27,24)
23 (22,22,30) (23,23,29) (24,24,28) (25,25,27) (26,26,27) (27,27,26) (28,28,25)
24 (23,23,31) (24,24,30) (25,25,29) (26,26,28) (27,27,28) (28,28,27) (29,29,26)
25 (24,24,31) (25,25,31) (26,26,31) (27,27,30) (28,28,29) (29,29,28) (30,30,28)
26 (25,25,31) (26,26,31) (27,27,31) (28,28,31) (29,29,30) (30,30,30) (31,31,29)
27 (26,26,31) (27,27,31) (28,28,31) (29,29,31) (30,30,31) (31,31,31) (31,31,30)
28 (27,27,31) (28,28,31) (29,29,31) (30,30,31) (31,31,31) (31,31,31) (31,31,31)
29 (28,28,31) (29,29,31) (30,30,31) (31,31,31) (31,31,31) (31,31,31) (31,31,31)
30 (29,29,31) (30,30,31) (31,31,31) (31,31,31) (31,31,31) (31,31,31) (31,31,31)
31 (30,30,31) (31,31,31) (31,31,31) (31,31,31) (31,31,31) (31,31,31) (31,31,31)

 

RGB→YJK の公式で変換してみても同じ値が得られます。
YJK→RGB の公式で元の値に戻ります。

 

RGB Y J K RGB
 (0,0,0) 0 0 (0,0,0)
(15,15,15) 13 2 2 (15,15,15)
(31,31,31) 27 4 4 (31,31,31)

 

実際に J・K が 0~4 の場合で表示してみました。
上が J・K=0、下が J・K=4、左右が Y=0~27 です。

 

 

J・K=2 の中心部分が最も灰色で、
上には青、下には黄色が入ってくる事がわかります。

ただし純粋な黒~灰色~白は左上~中央~右下となっています。
(左上が背景の黒と同じです)

 

J・K=0

 

J・K=2

 

J・K=4

 


実際のカラー画像から J・K の値を 0・2・4 に統一しました。
比較的容易にモノクロ画像化できます。
唯一変化のある Y の値は 1 ドットずつなので、
このようにした場合ギザギザは発生しません。

J・K=0 では青が入ってくる分濃くなるため、
画像や環境によってはむしろモノクロ画像のように見えるかもしれません。

J・K=2 が中間的に灰色となっているため、純粋なモノクロ画像のように見えます。
J・K=4 は黄色が入って薄くなるので、セピア調の表示になってきます。


ビットの対応

1 ドット=1 バイトの扱いで、これは SCREEN 8 と同じです。
横 4×縦 1 ドット=4 バイトが 1 まとまりです。

(0,0) から (0,3) が 1 まとまり、(0,4) から (0,7) が 1 まとまり……

(252,211) から (255,211) が 1 まとまり、となります。

VPOKE の場合も 0~3、4~7、…… と 1 まとまりになります。

 

SCREEN 11 と SCREEN 12 は自然画モード YJK を採用する以外は
SCREEN 8 と扱いが同じです。

VPOKE などで直接書き込む場合は SCREEN 10 も同じになります。

 

SCREEN 12

バイト ビット 解説
1 バイト目 YYYYYKKK K は下位 3 ビット
2 バイト目 YYYYYkKK K は上位 3 ビット(符号付)
3 バイト目 YYYYYJJJ J は下位 3 ビット
4 バイト目 YYYYYjJJ

J は上位 3 ビット(符号付)

純粋な YJK が入ります。Y はそのドットの座標に反映されますが、
J・K は 4 ドット共通になります。強調している小文字 j・k が符号部分です。

COLOR・POKE・LINE などでのカラーコードは 0~255 で
VPOKE で値を入れた場合と同じ状態になります。

つまり、VPOKE 0,255 と PSET(0,0),255 が同じ意味になります。

 

SCREEN 10・11

バイト ビット 解説
1 バイト目 YYYYAKKK K は下位 3 ビット
2 バイト目 YYYYAkKK K は上位 3 ビット(符号付)
3 バイト目 YYYYAJJJ J は下位 3 ビット
4 バイト目 YYYYAjJJ

J は上位 3 ビット(符号付)

SCREEN 12 異なる A を強調した黄色 にしました。

SCREEN 12 で使われていた Y の下 1 バイトが A に変わります。
A の値が 0 の場合、YJK の出力となり、Y はその座標の Y 値 0~15 です。

A の値が 1 の場合、COLOR 0~15 の RGB パレット出力となり、
Y の値は COLOR の値 0~15 です。

その他は SCREEN 12 と共通です。

 

SCREEN 11 の場合、カラーコードは 0~255 で、
COLOR・POKE・LINE などの扱いは VPOKE で値を入れた場合と
同じ状態になります。

これは SCREEN 12 と同じ扱い方です。
VPOKE 0,255 と PSET(0,0),255 が同じ意味になります。

 

SCREEN 10 の場合、カラーコードは 0~15 で、

COLOR・POKE・LINE などは RGB パレットで線画します。

(J・K の値を維持し、Y を COLOR 0~15・A を 1 に変更)

これにより、YJK の値を使用する事なく、
RGB パレットでの線画や文字の出力を可能にしています。

YJK の変更は BLOAD~,S や VPOKE などを使用する必要があります。


SCREEN 12 の画像を SCREEN 10・11 向けに変換する

SCREEN 12 の Y 下 1 ビット(=ビット 3)を 0 にすれば良い事になります。

SCREEN 11 または SCREEN 12 で画像を読み込んだ状態で次を実行します。

SCREEN 10 は RGB パレットで扱うので、LINE では行えません。
 

LINE(0,0)-(255,211),&HF7,BF,AND

 

変換しながらであれば、VPOKE などを行う直前で AND &HF7 にします。

Y の値が少なくなる分、色数は減ります。
よく見ると色の変化を目で確認できやすくなります。

 

この方法を用いる事で、SCREEN 12 向けに変換した画像を SCREEN 10 で表示し、

COLOR 0~15 の RGB パレットを用いて容易に描く事が可能です。

 

SCREEN 12 で

表示している画像

 

SCREEN 10・11 で
そのまま読むと……

 

&HF7 で AND すると

綺麗に表示できます

 


一方 SCREEN 10・11 で RGB パレット COLOR を使用していない場合は、

SCREEN 12 でそのまま表示可能です。

ただしこの場合 Y の値は 0~30 になるので、若干暗くなります。


J・K の対応

RGB から YJK への変換を行う場合、一つ問題になるのは 4 ドット分の J・K です。

  • 4 ドットのうち 1 ヶ所の J・K 値を扱い、他は破棄する
     →この場合、色に差があるとギザギザが出てきます。
  • J・K の平均値を使用する(4 ドット分を合計し、÷4 する)
     →この場合、色の差がある部分はぼかした状態になります。

※ ÷4 = 2 ビット右シフト


表示サンプル

どのような画像が YJK の表示に適しているでしょうか?
ここではいくつかの画像を .bmp ファイルから変換し、表示してみました。

  • オリジナル画像
  • SCREEN 8・256 色(RGB 各値の下位ビットを破棄)
  • SCREEN 12・YJK(J・K の値は 4 ドット中 1 ドットの値を使用)
  • SCREEN 12・YJK(J・K の値は 4 ドットの平均値)

ディザ(ディザリング)は行っていません。

各表示は更に JPEG へ変換させていますが、
上記の変換よりも画質の変化は見られないでしょう。

 

仙台・38mitsubachi のパンケーキ。🥞

同じ系統の色が多い画像です。

オリジナル画像

 

SCREEN 8

 


SCREEN 12
JK 4 ドットのうち1 ドットを使用

 

SCREEN 12
JK 4 ドットを平均の値で使用

 


YJK で得意とする画像が同系色の画像です。

パンケーキ、テーブル、シロップ入れなどがほぼ同系なので、
ほとんどギザギザが見えない画像になっています。

 

宮城県川崎町 釜房湖・釜房大橋 です。

比較的同系色になのですが……

オリジナル画像

 

SCREEN 8

 


SCREEN 12
JK 4 ドットのうち 1 ドットを使用

 

SCREEN 12
JK 4 ドットを平均の値で使用

 


空のグラデーションが天地で差があり、256 色ではおかしくなってしまっています。

色数の多い YJK でも色と色の境目が見えますが、
まだきれいに再現できている方でしょう。

濃い緑~水色~青系がほとんどなので、ギザギザなところはほとんど見当たりません。

 

仙台七夕 の七夕飾りです。

飾りは様々な色が使われています。

オリジナル画像

 

SCREEN 8

 


SCREEN 12
JK 4 ドットのうち 1 ドットを使用

 

SCREEN 12
JK 4 ドットを平均の値で使用

 


256 色も YJK も綺麗に表示できている画像です。

YJK をよく見ると、飾りと飾りの間にギザギザが出ているところがありますが、

飾りのデザインと重なって、あまり気になりません。

 

いろんな色の風船
🎈😍←風船大好き
オリジナル画像

 

SCREEN 8

 


SCREEN 12
JK 4 ドットのうち 1 ドットを使用

 

SCREEN 12
JK 4 ドットを平均の値で使用

 


単色のゴム風船も光加減でグラデーションになります。
256 色よりも多色な YJK が得意とします。

一方で YJK では風船の周りにギザギザが目立つところがあります。

1 ドット使用時は確実に見えますが、
4 ドット平均ではぼやけ、ある程度目立たなくなっています。

 

YJK には特に不向きだと思われる
カラーバーを変換してみました。

オリジナル画像

 

SCREEN 8

 


SCREEN 12
JK 4 ドットのうち 1 ドットを使用

 

SCREEN 12
JK 4 ドットを平均の値で使用

 


色の差がありすぎるため、色と色の間に白・黒の縦線が出てしまっています。

しかし、1 ドットを使用するよりも平均にした方が
その線は細くなっているように見えます。

1 ドットを使用する方がきれいな境目になっているように見える部分もあります。

このような画像は SCREEN 8・256 色が良いのですが、
SCREEN 8 では右下の変化がなく、真っ黒になっています。