【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする 
2017/12/17 Sun [edit]
色の形式はシステムによって違うので少し面倒だね。Unity の Color はその成分(r, g, b, a)が 0.0~1.0f であり、Android(Java)などで使われる ARGB(AARRGGBB) は int32(0x00000000~0xffffffff) で表現されている。今回はその相互変換をやってみよう。と言っても整数値と小数では完全に一致することはできないので、あくまで近似値となることに注意して欲しい。しかし、HTMLで使われる "#ffffffff" 形式にする分には完全一致にできるので、比較するなら Unity の ColorUtility を使う方法を覚えておいても良いかも知れない。

なお、これらの関数(メソッド)は現在配布しているプラグインにライブラリとして入っている。自分で作るのが面倒だと思ったら、ダウンロードして使うのも良いだろう。クラス名は「XColor」となっていて、フルパスは「Assets/FantomLib/Scripts/Graphics/XColor.cs」だ。
■Unity の Color → ARGB(int32) 変換
■ARGB(int32) → Unity の Color 変換
(※) Unity 2017.2.0f3 / Windows10(x64) で確認
■色形式:Unity の Color, ColorUtility と Android の ARGB(int32) の概要
まずは簡単に Unity と Android で使われる色形式の違いを確認しておこう。また Unity には色関連のユーティリティクラス(ColorUtility)もあるので、HTML形式("#ffffffff")も合わせて考えるとわかりやすい。

●Color → HTML 形式に変換
using UnityEngine;
Color color = new Color(0.4f, 0.6f, 0.8f, 1.0f); //#6699CCFF
string htmlString = ColorUtility.ToHtmlStringRGBA(color);
Debug.Log("htmlString = " + htmlString);
●HTML 形式 → Color に変換
using UnityEngine;
string htmlString = "#6699CCFF";
if (ColorUtility.TryParseHtmlString(htmlString, out color))
{
Debug.Log("color = " + color);
}
1つだけ注意するのは「Color → HTML 形式変換」では "ffffffff" のような文字列になるのだが、「HTML 形式 → Color 変換」では引数の文字列に "#" を付けて "#ffffffff" のようにしておかないと変換に失敗するということだ(※文字列の長さ "#fff" などはマニュアルを参照)。
ここからは色形式の相互変換をやってみよう。
■Unity の Color → ARGB(int32) 変換
Unity から Android(Java) で使われる形式に変換するには、大まかには2通りある。やり方はどちらでも良いが、1つは前述した「Color → HTML 形式に変換」と、値の正規化による変換「0.0~1.0f → 0~255」(Unity の Color の場合、元々値が正規化されてると考えて良い)だ。HTML 形式は各成分(頭から文字列をばらして "ff", "ff", "ff", "ff" → RR, GG, BB, AA と考える)[※図を参照] を抽出して、16進数→10進数 に変換すれば良い。
しかし、試しに正規化による変換:Color の成分(0.0~1.0f)に 255 を掛けて、0~255 の値に変換する際に、整数丸め(Mathf.RoundToInt())を使ってみたら上手く変換できるようなので(※通常は整数←→符号小数点 変換は完全に一致はできないので注意。切り捨てではHTML形式での変換と微妙に値が異なることがある)、ここでは少しでも簡潔にするためにも、各成分を計算で求める方法でやってみよう(また計算でできた方が高速でもあるので)。
●Color → ARGB(int32)形式の変換と各成分の抽出
using UnityEngine;
//Unity の Color → ARGB(int32)形式 に変換する
public static int ToIntARGB(Color color)
{
int r = RedValue(color);
int g = GreenValue(color);
int b = BlueValue(color);
int a = AlphaValue(color);
return (a << 24) | (r << 16) | (g << 8) | b; //ARGB
}
// Unity の Color から赤成分の int値(0~255)を抽出する
public static int RedValue(Color color)
{
return Mathf.RoundToInt(color.r * 255);
}
// Unity の Color から緑成分の int値(0~255)を抽出する
public static int GreenValue(Color color)
{
return Mathf.RoundToInt(color.g * 255);
}
// Unity の Color から青成分の int値(0~255)を抽出する
public static int BlueValue(Color color)
{
return Mathf.RoundToInt(color.b * 255);
}
// Unity の Color からアルファ成分の int値(0~255)を抽出する
public static int AlphaValue(Color color)
{
return Mathf.RoundToInt(color.a * 255);
}
//メインでは・・・
Color color = new Color(0.4f, 0.6f, 0.8f, 1.0f); //#6699CCFF
int argb = ToIntARGB(color);
Debug.Log("argb = " + argb);
ちなみに一旦 HTML 形式に変換して、各成分を抽出するには以下のようにすればできる(例では赤成分のみ)。
using UnityEngine;
Color color = new Color(0.4f, 0.6f, 0.8f, 1.0f); //#6699CCFF
string htmlString = ColorUtility.ToHtmlStringRGBA(color); //"RRGGBBAA"
string hex = htmlString.Substring(0, 2);
int red = Convert.ToInt32(hex, 16);
Debug.Log("red = " + red);
他の成分も同じようにすれば抽出→変換できる(ライブラリの旧バージョンはこの方法:現バージョンではコメントアウト)。
■ARGB(int32) → Unity の Color 変換
今度は逆に Android の int32(ARGB)から Unity の Color 形式に変換することをやってみよう。やり方は「Color → ARGB(int32)形式の変換」と真逆になる。これも HTML形式と正規化した値から計算する方法があるが(Unity の Color は元々正規化されてる値と考えて良い)、ここでは計算で求めてみよう。
●ARGB形式(int32) → Color 変換と各成分の抽出
using UnityEngine;
public static Color ToColor(int argb)
{
int r = RedValue(argb);
int g = GreenValue(argb);
int b = BlueValue(argb);
int a = AlphaValue(argb);
return new Color(r / 255f, g / 255f, b / 255f, a / 255f);
}
// ARGB 形式の int 値から赤成分の int値(0~255)を抽出する
public static int RedValue(int argb)
{
return ((argb & 0x00ff0000) >> 16);
}
// ARGB 形式の int 値から緑成分の int値(0~255)を抽出する
public static int GreenValue(int argb)
{
return ((argb & 0x0000ff00) >> 8);
}
// ARGB 形式の int 値から青成分の int値(0~255)を抽出する
public static int BlueValue(int argb)
{
return (argb & 0x000000ff);
}
// ARGB 形式の int 値からアルファ成分の int値(0~255)を抽出する
public static int AlphaValue(int argb)
{
return ((argb >> 24) & 0x000000ff);
}
//メインでは・・・
int argb = -10053172; //#6699CCFF
Color color = ToColor(argb);
Debug.Log("color = " + color);
Java には0埋めのビットシフト(>>>)というものがあるのだが(頭のビットを0で埋める)、C# には無いので(頭のビットが引き継がれる)アルファのような上位ビットをシフトして使うときは符号に注意(マスクで消すなど)。あとはビットシフトや AND(&), OR(|) 演算子は "&&", "||" とは異なり優先順位が低いので(そして言語によって微妙に違うので)、なるべく括弧でくくって正しい値になるようにした方が良いだろう。それ以外は前述の図を見れば、やってることはわかるだろう。各成分を抽出して変換(合成)しているだけだ。
ちなみに各成分を抽出して、一旦 HTML 形式にして ColorUtility で変換するには以下のようにすればできる。
using UnityEngine;
int argb = -10053172; //#6699CCFF
int r = RedValue(argb);
int g = GreenValue(argb);
int b = BlueValue(argb);
int a = AlphaValue(argb);
string htmlString = "#" + r.ToString("x2") + g.ToString("x2") + b.ToString("x2") + a.ToString("x2"); //"RRGGBBAA"
Color color;
if (ColorUtility.TryParseHtmlString(htmlString, out color))
{
Debug.Log("color = " + color);
}
ライブラリの旧バージョンはこの方法でやっている(現バージョンではコメントアウト)。試してみたが、どちらも結果は変わらないので計算の方が高速で良いだろう。ただ、Unity の Color の成分は float 型なので、比較するときは誤差に気をつけなくてはならない。そういうときは HTML形式にして比較するのもアリだと思う(今回紹介した方法だと完全に一致する)。
※この記事のスクリプトはプラグインのライブラリにも同梱されています。
※とりあえず試してみたい方は、最新版をビルドした apk デモをダウンロードできます。動作確認にもどうぞ。


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。
(関連記事)
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】Androidでカスタマイズしたダイアログを動的生成できるプラグインを作ってみた
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う
【Unity】Androidでスライダーで設定を変更するダイアログを使う
【Unity】Androidでスイッチで設定を変更するダイアログを使う
【Unity】Androidの選択ダイアログを使う
【Unity】Androidで日付・時刻選択ダイアログ(DatePicker, TimePicker)を使う
【Unity】Androidで数値・半角英数・パスワード入力ダイアログを使う
【Unity】Androidでテキスト入力ダイアログを使う
- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/286-2e156462
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |