intのピクセルデータから色を抽出する ビット演算子 - 萌えJava超入門
第六章 ビット演算子

intのピクセルデータから
色を抽出する

ビット演算子で、intのピクセルデータから
シフト演算子を使って
色の値を抽出する方法を紹介します。

目次

1.画像データの色情報


ビット演算子の使用例を紹介します。
画像データからピクセルデータを配列として取得することがあります、
ピクセルデータの形式はいろいろあるのですが、
ここでは、1ピクセルをintとして取得した場合を例にしてみます。


11111111_01010101_00001111_10101010
|-alpha-| |-red--| |-green| |-blue-|
青と赤の位置が入れ替わる場合があります。

1ピクセルをintで取得すると、
こんな風に8ビット刻みで
色データが入っている。
画像データって
以外と原始的なのね。
あ~いや、
敢えて低水準な書き方をしている。
もう少し使いやすい方法もあるけど
ビット演算子の理解にはちょうどいい。

画像を取扱うクラスは沢山ありますが、
大抵ピクセルデータを配列で取り出す手段が用意されています。
   例:BufferedImage getRasterメソッド など。
シューティングゲームを作ったりしていて
「透明色で塗りつぶす」といった操作を求めると、
「配列で操作したほうが楽だな」となったりならなかったりするのです。
   配列の話はもうちょっと後で。



2. intのピクセルデータから色を抽出する


ピクセル単位でデータをintで取得したときに、
ARGB(alpha,red,green,blue)の4チャンネルが8ビットずつ収まっています。
それぞれのチャンネルは、0~255 の値になります。
ビット演算子で、それぞれのチャンネルの値を取り出してみましょう。

右シフト(符無)して
AND(論理積)でマスクすると
切り出せるぞ。



11111111_01010101_00001111_10101010
|-alpha-|_|-red--|_|-green|_|-blue-|




青の値を抽出
11111111_01010101_00001111_10101010 & 00000000_00000000_00000000_11111111
  → 00000000_00000000_00000000_10101010
   青の値は10進数で 170



緑の値を抽出
11111111_01010101_00001111_10101010 >>> 8
   → 00000000_11111111_01010101_00001111

さらに、
00000000_11111111_01010101_00001111 & 00000000_00000000_00000000_11111111
   → 00000000_00000000_00000000_00001111
   緑の値は10進数で 15



赤の値を抽出
11111111_001010101_00001111_10101010 >>> 16
   → 00000000_00000000_11111111_01010101

さらに、
00000000_00000000_11111111_01010101 & 00000000_00000000_00000000_11111111
   → 00000000_00000000_00000000_01010101
   赤の値は10進数で 85



アルファー値(非透明度)を抽出
11111111_01010101_00001111_10101010 >>> 24
   → 00000000_00000000_00000000_11111111
アルファー値は10進数で 255



//Sample06_44.java
class Sample06_44 {
    public static void main(String[] args){
        int pix  = 0b11111111_01010101_00001111_10101010;
        int mask = 0b00000000_00000000_00000000_11111111;

        int alpha;
        int red;
        int green;
        int blue;
        String binStr;

        binStr = Integer.toBinaryString(pix);
        binStr = String.format("%32s", binStr);
        binStr = binStr.replace(' ', '0');
        System.out.println(binStr);
        System.out.println("-------------------------------------");

        /*Blue*/
        blue = pix & mask;

        /*Green*/
        green = pix >>> 8;
        green = green & mask;

        /*Red*/
        red = pix >>> 16;
        red = red & mask;

        /*Alpha*/
        alpha = pix >>> 24;

        /*表示*/

        System.out.println("Alpha:\t" + alpha);
        System.out.println("Red:\t" + red);
        System.out.println("Green:\t" + green);
        System.out.println("Blue:\t" + blue);
    }
}

コマンドライン
>javac Sample06_44.java
>java Sample06_44
11111111010101010000111110101010
-------------------------------------
Alpha:  255
Red:    85
Green:  15
Blue:   170




3.色をintのピクセルデータにパッケージする


今度はバラバラになった色データを
元に戻してみよう。
戻せるんだ。
真逆の手順をとる。
左シフトしてOR(論理和)でくっつけるぞ。


//Sample06_45.java
class Sample06_45 {
    public static void main(String[] args){

        int alpha = 255;
        int red = 85;
        int green = 15;
        int blue = 170;

        System.out.println("Alpha:\t" + alpha);
        System.out.println("Red:\t" + red);
        System.out.println("Green:\t" + green);
        System.out.println("Blue:\t" + blue);
        System.out.println("-------------------------------------");

        /*Green*/
        green = green << 8;

        /*Red*/
        red = red << 16;

        /*Alpha*/
        alpha = alpha << 24;

        /*結合*/
        int pix = alpha | red | green | blue;

        /*表示*/
        String binStr;
        binStr = Integer.toBinaryString(pix);
        binStr = String.format("%32s", binStr);
        binStr = binStr.replace(' ', '0');
        System.out.println(binStr);

    }
}

コマンドライン
>javac Sample06_45.java
>java Sample06_45
Alpha:  255
Red:  85
Green:  15
Blue:  170
-------------------------------------
11111111010101010000111110101010

難しかったと思うけど、
ここで挫折するくらいなら
飛ばして次に進もう。


お疲れ様でした。



© 2019 awasekagami