JavaScript おれおれ Advent Calendar 2011 – 8日目

CSSで色を表現する方法の一つにカラーコードというものがありまして、#55CC2Aみたいな感じで色を表現できますね。光の三原色RGB (Red, Green, Blue)を2桁の16進数で表現して連結したものです。

これをJavaScriptから扱うなら、そのまま16進数で0x55CC2Aみたいに扱うと見た目が似ていて楽チンそうです。(ちなみにアルファベットは大文字でも小文字でも可。)

この中から一色分だけ取得したりするには、ビット演算でムニャムニャするのが良いです。

(あるいはrgb()の形の表現でも良いでしょう。)

先に結論

// 取得
var code = 0x55cc2a;
var red   = code >> 16;         // => 0x55
var green = code >>  8 & 0xff;  // => 0xcc
var blue  = code       & 0xff;  // => 0x2a

console.log(red.toString(16));
console.log(green.toString(16));
console.log(blue.toString(16));
// 作成
var red   = 0x55;
var green = 0xcc;
var blue  = 0x2a;
var code = (red << 16) + (green << 8) + blue;  // 0x55cc2a

console.log(code.toString(16));

ビット演算をもりもり使ってますね。

16進数の下2桁を取り出す

ビット演算のAND&を使います。

var code = 0x55cc2a;
var blue = code & 0xff;  // => 0x2a

ビット演算のANDは、ビットの両方が1であれば1になる演算です。

     0x55CC2A (16) : 01010101 11001100 00101010 (2)
AND) 0x0000FF (16) : 00000000 00000000 11111111 (2)
---------------------------------------------------
     0x00002A (16) : 00000000 00000000 00101010 (2)

これで16進数で下2桁、つまり2進数で下8桁を得る事ができました。

16進数の桁をずらす

10進数で桁を右にn個ずらすには10n回割れば良いですね。

同様に16進数で桁をn個ずらすには16n回割れば良いです。

が、「16で割る」とは「2で4回割る」事と同義です。ここはビットシフトを使いましょう。2進数をずらすやつです。その方が高速なので。

16進数2桁分、つまり2進数で8桁分を右へずらします。

     0x55CC2A (16) : 01010101 11001100 00101010 (2)
>>)  8              >>>>>>>>
---------------------------------------------------
     0x0055CC (16) : 00000000 01010101 11001100 (2)

右に溢れた分は消滅します。

この状態で下位2桁を取れば、任意の位置の値を抽出できるわけですね。

ずらして取得する

2桁ずらして、

    0x55CC2A (16) : 01010101 11001100 00101010 (2)
>>)  8              >>>>>>>>
---------------------------------------------------
    0x0055CC (16) : 00000000 01010101 11001100 (2)

2桁取得。

     0x0055CC (16) : 00000000 01010101 11001100 (2)
AND) 0x0000FF (16) : 00000000 00000000 11111111 (2)
---------------------------------------------------
     0x0000CC (16) : 00000000 00000000 11001100 (2)

コードで書くとこう。

var code = 0x55cc2a;
var green = code >> 8 & 0xff;  // => 0xcc

redも同様に、2進数で右に16桁ずらしてから、0xffとのANDで得られます。ね、簡単でしょう?