ビット演算はプログラマにとって重要な基礎知識の一つである。
ビット演算でよく利用されるAND(論理積)、OR(論理和)、XOR(排他的論理和)の3つの演算について簡単に説明しておく。
表1 ビット演算子
表1にビット演算子を示す。AND演算子(&)は、両方のビットが1の場合は1を、それ以外の場合は0を返す。OR演算子(|)は、両方のビットが0の場合は0を、それ以外の場合は1を返す。XOR(^)は、1つのビットが0でもう1つのビットが1の場合は1を、それ以外の場合は0を返す。
&、|、^ の各演算子をboolean型の「真」と「偽」の2種類の値に対して定義されると、これらはビット論理演算子とみなされる。ビット論理演算子の動作はビット演算子と同じである。 1は「真」(true)、0は「偽」(false)を表す。
8ビットや16ビット、32ビット幅のデータに対してANDやORなどの演算をする場合は、表1のようにビット単位に実行する。例えば、x=22, y=19とすると、 x AND y は18になる。
図1 22 & 19 を計算する。
この演算の様子を図1に示す。まず22と19をそれぞれ2進数の8ビットで表現すると、00010110、00010011になる(参考)。このため、XとYのビットごとにANDをとると、00010010となる。これを10進数に直すと18になる。
Javaでは、論理式でAND演算、OR演算には&&(論理AND), || (論理OR)という演算子を使い、ビットごとの演算には &、|(ビットまたはビット論理演算子)を使う。
Javaで色を表現するときは、赤、緑、青の各成分濃度値(諧調値)を0〜255までの数値で表したうえで、これらの値を一つの32ビット幅の整数値にまとめて扱う。この整数には、図2のように下位8ビットに青の諧調値が、その上の8ビットに緑の諧調値が、さらにその上の8ビットに赤の諧調値が格納されている。
図2 色の表現形式ARGB
仮にこうした変数colorがあったとすると、この変数から赤、緑、青の各諧調値を取り出すにはどうすればいいか。
まず青の場合、下位8ビットが1、ほかが0であるようなビット・マスクを用意して、これとのANDをとればよい。つまり
blue = color & 0x0000ff
とすればよい。
ANDはJavaでは&として表す。ox0000ffの先頭にあるoxは、JavaやC/C++で16進数のことである。16進数のfは2進数の1111(10進数の15)を表すので、8ビット分が1の状態を16進数で「ff」と書けることである。
残りの緑と赤については単にマスクとのANDをとるだけでは求める諧調値にならない。例えば緑の場合、0x00ff00とのANDをとれば赤と青のビットの部分を0にすることができるが、結果が第8ビット〜第15ビットの計8ビットに位置しているために、0〜255の間に収まらない。
図3 緑の濃度値(階調値)を取りたい場合
この結果を0〜255の間、つまりint型変数の下位8ビットに収めるようにするためには、ANDを取った結果を右に8ビット分ずらす必要がある(図3)。
このように、ビットのイメージをまとめて右や左にずらす処理をビット・シフトと呼ぶ。Javaにはビット・シフトを行う演算子(シフト演算子)<<と>>がある。そこで、
green = (color & 0x00ff00) >> 8;
と記述すれば、ANDを取った結果を右に8ビットずらして求める結果を得ることができる。
同様に、赤の諧調値は
red = (color & 0xff0000) >> 16;
と書くことができる。