Tag Archives: コトバパレット

カラーコードの輝度を操作する(YCbCr値変換)

 カラーコード(#000000)の輝度を操作する処理を書きました(JavaScript)。
 カラーコードをYCbCr値に変換して輝度(Y)を操作することで実現しています。

 これはコトバパレットの実装の一部で、任意の色をを明るくしたり暗くしたりする必要があり、元々PHPで実装していました。
 今回のバージョンアップでクライアント側でも必要となり(Canvas)、JavaScriptで書き直しました。

function ctrlBrightness(cCode, value)
/* カラーコードと輝度の増減値を渡し、変換後のカラーコードを得ます */

function setBrightness(cCode, value)
/* カラーコードと輝度を渡し、変換後のカラーコードを得ます */

 また、以下の処理を関数化し、カラーコード、RGB値、YCbCr値の相互変換が行えるようにしています。

・カラーコード→RGB値
・カラーコード→YCbCr値
・RGB値→カラーコード
・RGB値→YCbCr値
・YCbCr値→カラーコード
・YCbCr値→RGB値

 なお、カラーコードには、6桁表記(#000000)と3桁表記(#000)がありますが双方に対応しています。
 但し、戻り値のカラーコードは全て6桁表記に統一されます。
 カラーネームとrgb値には対応していません。

 実装にあたり以下を参考にしました。

色空間 – Wikipedia
http://ja.wikipedia.org/wiki/色空間

RGB→YCbCr・YCbCr→RGB
http://eseuta.mine.nu/colorspace.html

 短いので貼り付けますが、GitHubにも置いてあります。
https://github.com/ivoryworks/colorcode-brightness.js

[cc lang=”JavaScript”]
/*
* Control brightness to ColorCode
*
* @param string cCode ColorCode(CSS format #000000 or #000)
* @param float value Brightness offset value
* @return string ColorCode(CSS format #000000)
*/
function ctrlBrightness(cCode, value) {
var ycbcr = colorCode2Ycbcr(formatColorCode(cCode));
ycbcr[0] = roundOff(ycbcr[0]+value, 255, -255);
return ycbcr2ColorCode(ycbcr);
}

/**
* Brightness set to ColorCode
*
* @param string cCode ColorCode(CSS format #000000 or #000)
* @param float value Brightness value(0 to 255)
* @return string ColorCode(CSS format #000000)
*/
function setBrightness(cCode, value) {
var ycbcr = colorCode2Ycbcr(formatColorCode(cCode));
ycbcr[0] = roundOff(value);
return ycbcr2ColorCode(ycbcr);
}

/**
* Convert ColorCode to YCbCr value
*
* @param string cCode ColorCode(CSS format #000000 or #000)
* @return array YCbCr value([0]==Y, [1]==Cb, [2]==Cr)
*/
function colorCode2Ycbcr(cCode) {
var rgb = colorCode2Rgb(formatColorCode(cCode));
return rgb2Ycbcr(rgb);
}

/**
* Convert YCbCr value to ColorCode
*
* @param array YCbCr value([0]==Y, [1]==Cb, [2]==Cr)
* @return string ColorCode(CSS format #000000)
*/
function ycbcr2ColorCode(ycbcr) {
var rgb = ycbcr2Rgb(ycbcr);
return rgb2ColorCode(rgb);
}

/**
* Convert RGB value to YCbCr value
*
* @param array RGB value([0]==R, [1]==G, [2]==B)
* @return array YCbCr value([0]==Y, [1]==Cb, [2]==Cr)
*/
function rgb2Ycbcr(rgb) {
var y = 0.298912 * rgb[0] + 0.586611 * rgb[1] + 0.114477 * rgb[2];
var cb = -0.16877709556951089920871620499976 * rgb[0] – 0.33122290443048910079128379500024 * rgb[1] + 0.5 * rgb[2];
var cr = 0.5 * rgb[0] – 0.41835760988634807613309598795016 * rgb[1] – 0.081642390113651923866904012049843 * rgb[2];
return new Array(y, cb, cr);
}

/**
* Convert YCbCr value to RGB value
*
* @param array YCbCr value([0]==Y, [1]==Cb, [2]==Cr)
* @return array RGB value([0]==R, [1]==G, [2]==B)
*/
function ycbcr2Rgb(ycbcr) {
var r = ycbcr[0] + 1.402176 * ycbcr[2];
var g = ycbcr[0] – 0.71448921433795138515984187135938 * ycbcr[2] – 0.34561921433795138515984187135938 * ycbcr[1];
var b = ycbcr[0] + 1.771046 * ycbcr[1];
return new Array(roundOff(r), roundOff(g), roundOff(b));
}

/**
* Convert ColorCode to RGB value
*
* @param string cCode ColorCode(CSS format #000000 or #000)
* @return array RGB value([0]==R, [1]==G, [2]==B)
*/
function colorCode2Rgb(cCode) {
cCode = formatColorCode(cCode);
return new Array(
parseInt(cCode[1]+cCode[2], 16)
,parseInt(cCode[3]+cCode[4], 16)
,parseInt(cCode[5]+cCode[6], 16)
);
}

/**
* Convert RGB value to ColorCode
*
* @param array RGB value([0]==R, [1]==G, [2]==B)
* @return string cCode ColorCode(CSS format #000000)
*/
function rgb2ColorCode(rgb) {
return ‘#’+(‘0’+rgb[0].toString(16).toUpperCase()).slice(-2)
+(‘0’+rgb[1].toString(16).toUpperCase()).slice(-2)
+(‘0’+rgb[2].toString(16).toUpperCase()).slice(-2);
}

/**
* Round off value(0 – 255)
*
* @param int value integer value
* @return int integer value(0…255)
*/
function roundOff(value, high, low) {
if (high == undefined) { high = 255; }
if (low == undefined) { low = 0; }
if (value > high) {
return high;
} else if (value < low) { return low; } return Math.floor(value); } /** * ColorCode formatting * * @param string cCode ColorCode(CSS format #000000 or #000) * @return string cCode ColorCode(CSS format #000000) */ function formatColorCode(cCode) { if (cCode.match(/^#[0-9A-F]{6}/i)) { return cCode; } else if (cCode.match(/^#[0-9A-F]{3}/i)) { return '#'+cCode[1]+cCode[1]+cCode[2]+cCode[2]+cCode[3]+cCode[3]; } else { return '#000000'; } } [/cc]

『コトバパレット』URL共有できるようになりました

パレット生成の言葉をURLに載せることができるようになりました。

こんなかんじ。

http://www.ivoryworks.com/大トロ

おもしろいの出たら共有しましょう。

『コトバパレット』リリースのおしらせ

 おまたせしました。できました。『コトバパレット』リリースします。できました。

コトバパレット

 『コトバパレット』は、言葉に応じてカラーパレットを生成するWebアプリです。
 言葉によってはイメージ通りの色になったり、予想外でかつ納得の色になったり、完全にありえない色が出たりしますが、それもこれもご愛嬌ということで。

 このWebアプリは、先日行われたGunma.web #4のLTで紹介したもので、その日の内にリリースする計画だったのですが、サーバで動作しない事がLTの準備段階で発覚し今日の今日までリリース出来ずじまいでいました。

 リリースが遅れた顛末等は別エントリにします。

 まずは遊んでやってください。

Gunma.web LT 『コトバパレット』まとめ

 先日のGunma.web #4でやらせてもらったLTのまとめです。
 感想等はこちら参照。

 まずはじめに、とても重要な事を言います。
 今回LTで紹介させてもらった『コトバパレット』というWebサービスは、LTの中でも言いましたが、未だにクライアントでしか動作してなく、公開に至っていません。
 下記スライドの中にURLが登場しますが、アクセスしても無駄ですのでもう少し待っていてください。泣きながら調整しています。ちゃんと動いたらリリースエントリします。

 まとめ、と言いましたが、当日は5分に収めることに注力するあまり、うまく喋れていませんでした。重要な事とか飛んじゃってたと思います。
 このエントリで少し補填したいと思ってます。

 まず、このアプリを作成するきっかけとなったのが、PANTONE社が毎年発表しているCOLOR OF THE YEARで、2011年を”Honeysuckle”とした事です。この事はGigazineの記事で知りました。
 スライド内にもありますが、「じゃあコンテンツにこのピンク色使えば2011年的にイカすんじゃなかろうか」と思って、でも配色難しくて「プログラムに作らせよう」と。
 今からして思えば、この時点で既に方向性が狂っていたと言えます。言っている事がおかしいです。

 実は、画像からパレットを作るというアイデアは、ホントの事を言うと完全なオリジナルではありません。

『Colors Palette Generator』画像からカラーパレットを一発作成

 これは、約2年前(2009/02/25)のエントリで、アップロードした写真からカラーパレットを作るというWebサービスを紹介しています。
 『コトバパレット』の出力結果が Light / Medium / Darkと3段階となっているのもこのサービスが由来です。
 私がこの、写真からパレットを生成するというアイデアを気に入っているのは、『現実世界の配色』を採用することができるからです。現実世界の配色には当然ながら不自然さがありません。現実に存在するからあたりまえですね。

 さて次に『ヒューリスティック』について少し書きます。
 これは乱暴に言うと「だいたい合ってる解法」で、スパムフィルタやアンチウイルスソフトウェアにも採用されています。
 『コトバパレット』は、これといった解法を持たないまま開発を進め、その過程で色々工夫(ヒューリスティックを考え、採用する)しながら出力(カラーパレット)の精度を上げていきました。これが非常に楽しかった。
 言葉を英訳してから検索語として扱うというボツアイデアもありました。
 
<人間はどうやって答えを得ているのか>

 今回のヒューリスティックは全てこれです。
 写真の端を切り取るというアイデアはその最たるものでしょう。

 最後に、『コトバパレット』の内部処理をざっくり書いておしまいにします。

1.画像の検索
 ユーザが入力した”言葉”をGoogleのWebAPIに渡して検索します。検索結果には、オリジナル画像のURLとサムネイル画像のURLが含まれていますが、サムネイルしか使いません。大きい画像は処理が大変だし、何といってもサムネイルはその画像の特徴が縮小されているからです。ありがとうGoogle。

2.グルーピング
 開発当初から「複数の画像から共通する色を採用する」という考えがあったので、その「複数の画像」の質を高めるため、ふさわしくない画像(性的じゃない意味で)をより分けるグルーピングを行います。
 処理は単純で、各画像を単純なパターンに変換(今回は8色以下に減色する)し、同じパターン同士をグループ化します。
 この8色減色はこのグルーピングでしか使用しません。出力結果となるパレットは、改めてサムネイル画像を512色以下に減色した結果を元にします。
 ちなみに『パターン化』は顔認識処理等にも使用されている考え方です。

3.色の採用
 質の良い画像が集まったら、元画像を512色以下に減色し、たくさん使われていて(ピクセルの数)、かつ複数の画像で使われている色の上位8色を基本パレットとします。

4.パレット生成
 最後に基本パレット(Medium)の明度を上下させ、明るいパレット(Light)と暗いパレット(Dark)を作っておしまい。
 明度の調整は、単純にRGBを上下させれば良いかと思っていたのですが大きな間違いでした。

RGBとYCrCbの変換(明度と色差)

 質疑応答の時間で「結局イカしたサイトデザインはどうなったのか」という質問がありました。これは非常に嬉しかったですね。

 最初の思いつきはどうにもなっていません。

 最初に考えた物がそのまま出来たらLT的においしくないからです。

Gunma.web #4 に行ってきたよ

 2011/02/12 Gunma.web #4 に参加してきました。今回で3回めの参加になります(ATND)。
 今回もLTやってきました。

 会場はトラットリア・シュンという高崎のイタリア料理店。
 料理おいしかったです。

 参加者13人でLT7本というボリュームのある内容となりました。
 コンスタントにこれくらいの人数集まると良いですね。LTもガシガシやろうぜ!

 では簡単に各LTの紹介。

@parrot_studio: 『思い通りにいかないのがWebなんて割り切りたくないから』
 LT上手です。勉強になります。
 コンテンツで使用する画像を1枚にまとめ、クライアントで切り取って使うことにすることでレスポンス向上を狙うというおはなし。
 複数の画像を1枚に集約したりCSSを書いたりするメンテナンスコストと、ユーザエクスペリエンスのトレードオフになるけど、結果として全体的なサーバーコネクション数が減るので、nクライアントとしてのレスポンス向上が望めるんじゃないかな。ナロー時代だったらもっと効果が期待できたかもしれない。
 質疑応答の中で出た、画像切り貼りの処理コストについては、今はクライアント側が極端に貧弱でないかぎり無視できるんじゃないかと思う。
 コミPo!には触れません。こちらをどうぞ。

@ivoryworks: 『コトバパレット』
 自分のLTです。ひどい有様でした。あとで改めてエントリします。

@toshi6: 『Jenkins CI』
 継続的インテグレーション(CI)ツールJenkins CIの紹介。デモもあって良かった。
 CIはWebでない私の仕事でも使うことがあります。Jenkinsじゃないけど。
 あと、ThinkPadの素晴らしさを分かち合いたいと思いました。LTと関係ありません。すみません。

@kyaro_os: 『映画公開記念!数値でみるFacebook』
 この国はFacebookが既存SNSを飲み込む相が既にでておる。と仰っていました。
 個人的にmixiとFacebookのログイン比率が逆転してきたので何だかそうなのかもしれないと思ったり。
 あとiPadのプレゼン良かったです。去年のLL Tiger弾さんが使ってたの見た以来です。
 ピンチアウト、ピンチイン便利ですね。いいね!

@tsurumau: 『Viを選ぶ理由』
 ViイイヨーVi。というおはなし。エディタ。永遠の論争テーマですね。
 つい先日twitterで「おまえらエディタ何使ってるか教えろ」みたいな事を言ったこともあり、質疑応答の時間でついヒドい事を言ってしまった件については反省しています。だって言いたかったんだもの。

@kanayannet: 『趣味で群馬のsmart_phoneサイト作ってみました』
 まだまだその全貌は公にできない感じの可能性は未知数でチラ見せ的な言うなれば発展途上というか、要するにまだできてない感じのfor Gunmmer(グンマー)なアプリの紹介。
 鶴舞うロケーションベースのアプリです。個人的にとても楽しみにしています。

@terakuma:
 いろいろな事情があって内容書けません。
 モノクロ写真の怖いおじさんが出てくる話だったと思います。
 あとお金がどうのこうのと言っていました。よく覚えていません。

 Gunma.web、回を重ねるごとに楽しさの密度が増しているように思っています。
 自分は「毎回LTやる」という制約を自らに課しているため、参加する以前よりクリエイティブな日々を送れています。ありがとう。