【Unity】【描画処理】16ビットカラーの中身

投稿者: | 2016年11月16日

はじめに

こんばんは、代表の堂前です!

今回はUnityというよりも一般的な描画関連の話をしていこうと思います。
取り上げるのは「16ビットカラー」についてです。(RGB565やARGB1555といったものです。)
やや基本的な話ですが、改めて紹介していきます。

※検証に利用したのはMacのUnity5.4.1p2になります。


カラーフォーマット

描画では当然の如くテクスチャを扱うことがあり、それらはカラーで構成されています。
最近ではHDRディスプレイなどの登場によりカラーフォーマットもfloatのものが出たりしていますが、基本はARGB8888(Unityだと「ARGB32」)が主流になると思います。
(注・フォーマットという意味では圧縮テクスチャが多く使われますが、上記はカラー画素としてのフォーマットを指します。)

ただARGB8888だと1ピクセルにつき32ビット、つまり4バイトも消費してしまいます。
それだとメモリ消費や負荷が心配になるので、1ピクセルのサイズを減らしたRGB565ARGB1555というものを利用することがあります。

これらは数字を見て分かる通り、ARGB8888では各要素に8ビット、つまり256段階利用できます。
反面RGB565やARGB1555等では、要素で5もしくは6ビット、つまり32もしくは64段階の階調となります。(25=32という理屈です。)

A R G B
ARGB8888 8ビット
(28=256段階)
8ビット
(28=256段階)
8ビット
(28=256段階)
8ビット
(28=256段階)
RGB565 5ビット
(25=32段階)
6ビット
(26=64段階)
5ビット
(25=32段階)
ARGB1555 1ビット
(21=2段階)
5ビット
(25=32段階)
5ビット
(25=32段階)
5ビット
(25=32段階)

ビット数が少ない分、データサイズは減ることになります。
ただしかし階調が減るということは情報として欠落していると言えます。

16ビットカラーでよく言われるのは「グラデーションが汚い」です。
見てもらえば一目瞭然で、これは階調が少ないために起こっています。

ARGB8888 color16_grad32
RGB565 color16_grad16

このグラデーション問題の回避はディザ法であったり誤差拡散法で軽減が出来ますが、今回はその話はしません。
今回は32段階、もしくは64段階となっている階調が、実際どういう色になっているかというのを見ていきます。


階調の中身

5ビットもしくは6ビットで階調を扱いますが、コンピュータとしては8ビットに拡張して扱います。
8ビットなので、カラーの値は0〜255となります。
イメージとしては下図の様になります。

color16_bit5_info

5ビットもしくは6ビットが上位に来る形になりますが、余った下位はどうなるのでしょう?
例えば常に0が入る場合、上限値が255ではなく248になってしまい、逆に常に1の場合は下限値が7になってしまいます。あまり好ましいと言えません。

常に0で埋める 常に1で埋める
color16_low_full0 color16_low_full1

そこで以下のプログラムを組んで確認をしてみました。

void Start ()
{
    // テクスチャ作成
    Texture2D   texture = new Texture2D( 256, 1, TextureFormat.RGB565, false );
    for (int x = 0;x < texture.width;++x) {
        texture.SetPixel( x, 0, new Color32( (byte)x, (byte)x, (byte)x, (byte)x ) );
    }
    texture.Apply();

    // 中身を照会
    string      str = "";
    Color32[]   colors = texture.GetPixels32();
    for (int x = 0;x < colors.Length;++x) {
        str += ( x + " : ( " + colors[x].r + ", " + colors[x].g + ", " + colors[x].b + ", " + colors[x].a + " )\n" );
    }
    Debug.Log( str );
}

これは内部的にRGB565のテクスチャをグラデーション(256段階)で作成し、再度カラー値を確認するものです。
結果は以下の通りになります。(一部省略)

0 : ( 0, 0, 0, 255 )
  :
  :
4 : ( 0, 4, 0, 255 )
5 : ( 8, 4, 8, 255 )
  :
  :
12 : ( 8, 12, 8, 255 )
13 : ( 16, 12, 16, 255 )
  :
  :
20 : ( 16, 20, 16, 255 )
21 : ( 24, 20, 24, 255 )
  :
  :
28 : ( 24, 28, 24, 255 )
29 : ( 33, 28, 33, 255 )
  :
  :
37 : ( 33, 36, 33, 255 )
38 : ( 41, 36, 41, 255 )
  :
  :
45 : ( 41, 44, 41, 255 )
46 : ( 49, 44, 49, 255 )
  :
  :
53 : ( 49, 52, 49, 255 )
54 : ( 57, 52, 57, 255 )
  :
  :
61 : ( 57, 60, 57, 255 )
62 : ( 66, 60, 66, 255 )
  :
  :
69 : ( 66, 69, 66, 255 )
70 : ( 74, 69, 74, 255 )
  :
  :
78 : ( 74, 77, 74, 255 )
79 : ( 82, 81, 82, 255 )
  :
  :
86 : ( 82, 85, 82, 255 )
87 : ( 90, 85, 90, 255 )
  :
  :
94 : ( 90, 93, 90, 255 )
95 : ( 99, 93, 99, 255 )
  :
  :
102 : ( 99, 101, 99, 255 )
103 : ( 107, 101, 107, 255 )
  :
  :
111 : ( 107, 109, 107, 255 )
112 : ( 115, 113, 115, 255 )
  :
  :
119 : ( 115, 117, 115, 255 )
120 : ( 123, 121, 123, 255 )
  :
  :
127 : ( 123, 125, 123, 255 )
128 : ( 132, 130, 132, 255 )
  :
  :
135 : ( 132, 134, 132, 255 )
136 : ( 140, 138, 140, 255 )
  :
  :
143 : ( 140, 142, 140, 255 )
144 : ( 148, 146, 148, 255 )
  :
  :
152 : ( 148, 154, 148, 255 )
153 : ( 156, 154, 156, 255 )
  :
  :
160 : ( 156, 162, 156, 255 )
161 : ( 165, 162, 165, 255 )
  :
  :
168 : ( 165, 170, 165, 255 )
169 : ( 173, 170, 173, 255 )
  :
  :
176 : ( 173, 174, 173, 255 )
177 : ( 181, 178, 181, 255 )
  :
  :
185 : ( 181, 186, 181, 255 )
186 : ( 189, 186, 189, 255 )
  :
  :
193 : ( 189, 195, 189, 255 )
194 : ( 198, 195, 198, 255 )
  :
  :
201 : ( 198, 203, 198, 255 )
202 : ( 206, 203, 206, 255 )
  :
  :
209 : ( 206, 211, 206, 255 )
210 : ( 214, 211, 214, 255 )
  :
  :
217 : ( 214, 219, 214, 255 )
218 : ( 222, 219, 222, 255 )
  :
  :
226 : ( 222, 227, 222, 255 )
227 : ( 231, 227, 231, 255 )
  :
  :
234 : ( 231, 235, 231, 255 )
235 : ( 239, 235, 239, 255 )
  :
  :
242 : ( 239, 243, 239, 255 )
243 : ( 247, 243, 247, 255 )
  :
  :
250 : ( 247, 251, 247, 255 )
251 : ( 255, 251, 255, 255 )
  :
  :
255 : ( 255, 255, 255, 255 )

結果ですが、RならびにBの5ビットの部分のみ注目する形にしています。
32階調あるのですが、0から始まり、255できちんと終わっています。

これは結論から言えば、上位に設定した5ビットもしくは6ビットの中の上位を、そのまま下位に持って行ってます。
図を見てもらうと早いでしょう。

color16_bit5_copy

これだと指定数値が大きければ大きいほど下位も大きくなり、小さい時は下位も小さくなるので、常に0の時の様な偏りは発生しません。

最小値 最大値
color16_low_copy0 color16_low_copy1

これを行うことで5ビットや6ビットでもある程度の精度で、カラーを利用しているというのが分かります。

逆に自前で誤差拡散法等のピクセル加工を行う場合、このルールを念頭におく必要があるでしょう。


 

 

【免責事項】
本サイトでの情報を利用することによる損害等に対し、株式会社ロジカルビートは一切の責任を負いません。

【Unity】【描画処理】16ビットカラーの中身」への1件のフィードバック

  1. ピンバック: 【描画処理】【数学】16ビットカラーの中身(補足編) – 株式会社ロジカルビート

コメントは停止中です。