色のトゥイーンの実験
http://ja.wikipedia.org/w/index.php?title=HSV%E8%89%B2%E7%A9%BA%E9%96%93 を見ながら色のトゥイーンの方法を探ってみた
// forked from kaikoga's ガンマ補正してみた
// forked from chaiyuttochai's how i can make movie clipe illastrate as a dot pixel?
// forked from hacker_7i4tn9on's forked from: The same brightness looks different.
// forked from borealkiss's The same brightness looks different.
// http://ja.wikipedia.org/w/index.php?title=HSV%E8%89%B2%E7%A9%BA%E9%96%93 を見ながら色のトゥイーンの方法を探ってみた
package {
import flash.display.Sprite;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Custom;
import org.libspark.betweenas3.tweens.ITween;
[SWF(width=465, height=465, backgroundColor=0x0)]
public class main extends Sprite{
private static const STAGE_SIZE:int = 465;
private static const RECT_SIZE:int = 100;
private static const SCREEN_GAMMA:Number = 2.2;
private static var SOURCE:Color;
private static var TARGET:Color;
private var rect1:RectSprite;
private var rect2:RectSprite;
private var rect3:RectSprite;
private var rect4:RectSprite;
public function main(){
SOURCE = Color.rgb(255, 0, 0);
TARGET = Color.rgb(0, 192, 64);
this.addRects();
}
public function blend(a:Number, b:Number, pos:Number):Number {
return a * (1 - pos) + b * pos;
}
public function set time(value:Number):void {
//RGBの値ごとにトゥイーン
this.rect1.color = Color.rgb(
blend(SOURCE.red, TARGET.red, value),
blend(SOURCE.green, TARGET.green, value),
blend(SOURCE.blue, TARGET.blue, value)
);
//HSVの値ごとにトゥイーン
this.rect3.color = Color.hsv(
blend(SOURCE.hue, TARGET.hue, value),
blend(SOURCE.saturation, TARGET.saturation, value),
blend(SOURCE.value, TARGET.value, value)
);
//上二つをブレンド
this.rect2.color = this.rect1.color.mix(this.rect3.color, 0.5);
//HSV色空間を円柱と見て空間内をトゥイーン
var x:Number = blend(
Math.cos(SOURCE.hue / 180 * Math.PI) * SOURCE.saturation,
Math.cos(TARGET.hue / 180 * Math.PI) * TARGET.saturation,
value);
var y:Number = blend(
Math.sin(SOURCE.hue / 180 * Math.PI) * SOURCE.saturation,
Math.sin(TARGET.hue / 180 * Math.PI) * TARGET.saturation,
value);
this.rect4.color = Color.hsv(
Math.atan2(y, x) / Math.PI * 180,
Math.sqrt(x * x + y * y),
blend(SOURCE.value, TARGET.value, value)
);
}
private function addRects():void{
this.rect1 = new RectSprite(RECT_SIZE, RECT_SIZE, SOURCE.color);
this.rect1.x = STAGE_SIZE * 0.2 - RECT_SIZE * 0.5;
this.rect1.y = 50;
this.addChild(this.rect1);
this.rect2 = new RectSprite(RECT_SIZE, RECT_SIZE, SOURCE.color);
this.rect2.x = STAGE_SIZE * 0.5 - RECT_SIZE * 0.5;
this.rect2.y = 50;
this.addChild(this.rect2);
this.rect3 = new RectSprite(RECT_SIZE, RECT_SIZE, SOURCE.color);
this.rect3.x = STAGE_SIZE * 0.8 - RECT_SIZE * 0.5;
this.rect3.y = 50;
this.addChild(this.rect3);
this.rect4 = new RectSprite(RECT_SIZE, RECT_SIZE, SOURCE.color);
this.rect4.x = STAGE_SIZE * 0.5 - RECT_SIZE * 0.5;
this.rect4.y = 250;
this.addChild(this.rect4);
var tween:ITween = BetweenAS3.tween(this, {time: 1}, {time: 0}, 4);
tween = BetweenAS3.serial(tween, BetweenAS3.reverse(tween));
tween.stopOnComplete = false;
tween.play();
}
}
}
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
class RectSprite extends Sprite {
private var rectWidth:Number;
private var rectHeight:Number;
private var textField:TextField;
private var _colorValue:uint;
public function set caption(value:String):void {
this.textField.text = value;
}
public function get colorValue():uint {
return this._colorValue;
}
public function set colorValue(value:uint):void {
this._colorValue = value;
this.graphics.clear();
this.graphics.beginFill(value);
this.graphics.drawRect(0, 0, this.rectWidth, this.rectHeight);
this.caption = value.toString(16);
}
public function get color():Color {
return new Color(this._colorValue);
}
public function set color(value:Color):void {
this.colorValue = value.color;
}
public function RectSprite(width:Number, height:Number, color:uint) {
this.rectWidth = width;
this.rectHeight = height;
var textFormat:TextFormat = new TextFormat();
textFormat.size = 16;
textFormat.color = 0xFFFFFF;
textFormat.align = TextFormatAlign.CENTER;
this.textField = new TextField();
this.textField.width = width * 2;
this.textField.height = 100;
this.textField.x = -width * 0.5;
this.textField.y = height + 20;
this.textField.defaultTextFormat = textFormat;
this.addChild(this.textField);
this.colorValue = color;
}
}
class Color {
public var color:uint;
public function Color(color:uint) {
this.color = color;
}
public function get red():uint {
return (this.color >> 16) & 255;
}
public function get green():uint {
return (this.color >> 8) & 255;
}
public function get blue():uint {
return (this.color) & 255;
}
public function set red(value:uint):void {
this.color = (this.color & 0xff00ffff) | ((value & 255) << 16);
}
public function set green(value:uint):void {
this.color = (this.color & 0xffff00ff) | ((value & 255) << 8);
}
public function set blue(value:uint):void {
this.color = (this.color & 0xffff00ff) | ((value & 255));
}
public static function rgb(r:int, g:int, b:int):Color {
return new Color(((r & 255) << 16) | ((g & 255) << 8) | ((b & 255) << 0));
}
private function get maxRGB():uint {
return Math.max(this.red, this.green, this.blue);
}
private function get minRGB():uint {
return Math.min(this.red, this.green, this.blue);
}
private function get dynRGB():uint {
return this.maxRGB - this.minRGB;
}
public function get hue():Number {
switch (this.maxRGB) {
case this.red:
return 60 * (this.green - this.blue) / this.dynRGB + 0;
case this.green:
return 60 * (this.blue - this.red) / this.dynRGB + 120;
case this.blue:
return 60 * (this.red - this.green) / this.dynRGB + 240;
}
return 0;
}
public function get saturation():Number {
return this.dynRGB / this.maxRGB;
}
public function get value():Number {
return this.maxRGB / 255;
}
public function set hue(value:Number):void {
this.color = hsv(value, this.saturation, this.value).color;
}
public function set saturation(value:Number):void {
this.color = hsv(this.hue, value, this.value).color;
}
public function set value(value:Number):void {
this.color = hsv(this.hue, this.saturation, value).color;
}
public static function hsv(h:Number, s:Number, v:Number):Color {
v *= 255;
if (s == 0) {
return rgb(v, v, v);
}
if (h < 0) {
h = 360 + (h % 360);
}
var Hi:int = Math.floor(h / 60) % 6;
var f:Number = h / 60 - Hi;
var p:Number = v * (1 - s);
var q:Number = v * (1 - f * s);
var t:Number = v * (1 - (1 - f) * s);
switch (Hi) {
case 0:
return rgb(v, t, p);
case 1:
return rgb(q, v, p);
case 2:
return rgb(p, v, t);
case 3:
return rgb(p, q, v);
case 4:
return rgb(t, p, v);
case 5:
return rgb(v, p, q);
}
return rgb(0, 0, 0);
}
public function mix(target:Color, rate:Number = 0.5):Color {
var nr:Number = 1 - rate;
return rgb(this.red * nr + target.red * rate, this.green * nr + target.green * rate, this.blue * nr + target.blue * rate);
}
private function gamma(a:int, g:Number):int {
return 255 * Math.pow(a / 255, 1 / g);
}
}