﻿function parseRgbString(str) {
	var re = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/i;

	var m = re.exec(str);
	if(m == null) {
		alert("ERROR: " + str + " doesn't look like an RGB string");
		return [0, 0, 0];
	}
	return [parseInt(m[1]), parseInt(m[2]), parseInt(m[3])];
}

function parseColorStringToRgb(str) {
	if(str.length == 7) return rgbToString(hexToRgb());
	return parseRgbString(str);
}

function rgbToString(rgb) {
	return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
}

function rgbStringToHex(str) {
	return rgbToHex(parseRgbString(str));
}

function rgbToHex(rgb) {
	var r = rgb[0];
	var g = rgb[1];
	var b = rgb[2];

	var r_hex = r.toString(16);
	var g_hex = g.toString(16);
	var b_hex = b.toString(16);

	if(r_hex.length < 2) r_hex = '0' + r_hex;
	if(g_hex.length < 2) g_hex = '0' + g_hex;
	if(b_hex.length < 2) b_hex = '0' + b_hex;

	return '#' + r_hex + g_hex + b_hex;
}

function hexToRgb(hex) {
	var match = /#?(\w{2})(\w{2})(\w{2})/.exec(hex);
	if(match == null) return null;

	var r = parseInt(match[1], 16);
	var g = parseInt(match[2], 16);
	var b = parseInt(match[3], 16);

	return [r, g, b];
}

// returns HSV value in [6, 1, 1] format
function rgbToHsv(rgb) {
	var r = rgb[0] / 255;
	var g = rgb[1] / 255;
	var b = rgb[2] / 255;

	var i;
	var x = Math.min(r, g, b);
	var v = Math.max(r, g, b);
	if(v == x) return [0, 0, v];

	var f = (r == x) ? g - b : ((g == x) ? b - r : r - g);
	i = (r == x) ? 3 : ((g == x) ? 5 : 1);

	var h = i - f / (v - x);
	var s = (v - x) / v;
	return [h, s, v];
}

// takes HSV value in [6, 1, 1] format
function hsvToRgb(hsv) {
	var h = hsv[0];
	var s = hsv[1];
	var v = hsv[2];

	var i;
	i = Math.floor(h);
	var f = h - i;
	if(!(i & 1)) f = 1 - f; // if i is even
	var m = v * (1 - s);
	var n = v * (1 - s * f);
	switch(i) {
		case 6:
		case 0:
			return rgb255(v, n, m);
		case 1:
			return rgb255(n, v, m);
		case 2:
			return rgb255(m, v, n);
		case 3:
			return rgb255(m, n, v);
		case 4:
			return rgb255(n, m, v);
		case 5:
			return rgb255(v, m, n);
	}
}

// converts rgb in [1.0, 1.0, 1.0] format to [255,255,255]
function rgb255(r, g, b) {
	return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

function rgbAlphaComposite(rgbA, rgbB, aAlpha) {
	if(rgbA == null) return rgbB;
	return [
		rgbAOverB(rgbA[0], rgbB[0], aAlpha),
		rgbAOverB(rgbA[1], rgbB[1], aAlpha),
		rgbAOverB(rgbA[2], rgbB[2], aAlpha)
	];
}

function rgbAOverB(a, b, aAlpha) {
	return Math.round(a * aAlpha + b * (1 - aAlpha));
}
