adjustColor2

convert colors to eye-friendly - webページの配色を目に優しく変更します (Flash対応)

目前為 2015-06-12 提交的版本,檢視 最新版本

// ==UserScript==
// @name        adjustColor2
// @namespace   http://chiebukuro.yahoo.co.jp/my/gbjyn273
// @author Syakku
// @description	convert colors to eye-friendly - webページの配色を目に優しく変更します (Flash対応)
// @include     *
// @version     1.3
// @run-at     document-start  
// ==/UserScript==

//	================≪ OPTION ≫================

	//	----------------< white" & "black" color >----------------
	var FILTER_COLOR_W = "rgb(234, 229, 227)";
	var FILTER_COLOR_B = "rgb(41, 34, 29)";
	var INNER_COLOR_W = "rgb(211, 203, 198)";
	var INNER_COLOR_B = "rgb(41, 34, 29)";	//	gb is disabled
	
	//	OPTION : apply to Flash object
	var FLASH = true;
	
	//	OPTION : skip <a> tag (link anchor)
	//	OPTION : <a> タグ、つまりリンク文字列を処理から除外します
	//	ex: [] or ["google.co.jp", "youtube", "&link=important"] or [*]
	var _A_SKIP_URL = ["*"];
	
	
// ================≪ 初期化 ≫================
	var _win = document.defaultView;	
	
	var fCw = rgbSplit(FILTER_COLOR_W);
	var fCb = rgbSplit(FILTER_COLOR_B);
	var iCw = rgbSplit(INNER_COLOR_W);
	var iCb = rgbSplit(INNER_COLOR_B);
	
	// ----------------< インナーがフィルターを超えていたら修正 >----------------
	for (var i=0; i<3; i++){
		if (iCw[i] > fCw[i]){iCw[i] = fCw[i];}
		if (iCb[i] < fCb[i]){iCb[i] = fCb[i];}
	}
	
	// ----------------< フィルタ関連の初期化 >----------------
	var fColor = createFilter(fCw, fCb);
	var filterR = fColor[0], filterG = fColor[1], filterB = fColor[2],	filterA = fColor[3], filterAa = 1-filterA;
	
	//	色変換で使うので先に計算
	var filterRA = filterR * filterA, filterGA = filterG * filterA, filterBA = filterB * filterA;
	var _pr = (iCw[0] - iCb[0]) / 255, _pg = (iCw[1] - iCb[1]) / 255, _pb = (iCw[2] - iCb[2]) / 255;
	var _pr2 = iCb[0], _pg2 = iCb[1], _pb2 = iCb[2];
	
	// ----------------< 色変換の結果保持配列 >----------------
	var list = [];
	var lFg = [];
	var lCount = 0;


	// ----------------< 背景画像処理 >----------------
	var bgFilter = createBgFilter();
	var bgfCount = bgFilter.substring(0, 30);
	var bgfcLength = bgfCount.length;
	
	function createBgFilter(){
		var tw=[], tb=[];
		tw[0] = Math.floor((iCw[0] - filterRA) / filterAa);
		tw[1] = Math.floor((iCw[1] - filterGA) / filterAa);
		tw[2] = Math.floor((iCw[2] - filterBA) / filterAa);
		tb[0] = Math.floor((iCb[0] - filterRA) / filterAa);
		var bfColor = createFilter(tw, tb);
		var _rgba = bfColor[4];
		return("linear-gradient(" + _rgba + ',' + _rgba + "),");
	}

	// ----------------< URLフィルタ >----------------
	var _skip = false;
	for (var i=0; i<_A_SKIP_URL.length; i++){
		if (location.href.indexOf(_A_SKIP_URL[i]) !== -1 || _A_SKIP_URL[i] === "*"){_skip = true;}
	}
	
	
	
// ################################################ //
// ################### メイン処理部 ################### //
// ################################################ //


// ================≪ 起動処理 ≫================
	if (window === window.parent){loadFilter();}
	_win.addEventListener("DOMContentLoaded", afterTouch, false);
	
	if (FLASH === true){_win.addEventListener("DOMContentLoaded", flashMode, false);}
	
// ================≪ フィルタの適用 ≫================
function loadFilter(){
	document.getElementsByTagName("html")[0].style.height = "100%";
	
	var _filter = document.createElement("ac_filter"); 
	_filter.id = "adjustColor"; 
	_filter.style.backgroundColor = fColor[4];
	_filter.style.pointerEvents = "none";
	_filter.style.height = "100%";
	_filter.style.width = "100%";
	_filter.style.display = "block";
	_filter.style.position = "fixed";
	_filter.style.zIndex = "2147483647";

	document.getElementsByTagName("html")[0].appendChild(_filter);
}


// ================≪ 追加処理 ≫================
function afterTouch(){
	
    var elm = document.getElementsByTagName("*");
	var elm_length = elm.length;

	for (var i = 0; i < elm_length; i++) {

		var tElm = elm[i];
		// <A>タグ
		if (tElm.tagName === "A" && _skip === true) {continue;}
        var style = _win.getComputedStyle(tElm, null);
		var fgColor = style.getPropertyValue("color");
		
		// ----------------< 背景 >----------------
		fg:{
			
			//	処理する必要のないカラーは省く
			for (var n=0; n<lCount; n++){
				if (fgColor === list[n]){break fg;}
			}
						
			//	既存のカラーは省エネ
			for (var n=0; n<lCount; n++){
				if (fgColor === lFg[n]){
					tElm.style.color = list[n];
					break fg;
				}
			}

			var _tColorF = convColor(fgColor);
			lFg[lCount] = fgColor;
			list[lCount] = _tColorF;
			lCount++;
			tElm.style.color = list[n];
		}
	}
}


//	================ <背景色レンジ縮小 ≫================
function convColor(_bg) {

	var _col = rgbSplit(_bg);
	
    var _colR = _col[0] * _pr + _pr2*1;
    var _colG = _col[1] * _pg + _pg2*1;
    var _colB = _col[2] * _pb + _pb2*1;
	
	_colR = Math.floor((_colR - filterRA) / filterAa);
	_colG = Math.floor((_colG - filterGA) / filterAa);
	_colB = Math.floor((_colB - filterBA) / filterAa);

    if (typeof _col[3] === "undefined") {
        return ("rgb(" + _colR + ", " + _colG + ", " + _colB + ")");
    }
    return ("rgb(" + _colR + ", " + _colG + ", " + _colB + ", " + _col[3] + ")"); //	rgba
}


// ================≪ RGB値の分割 ≫================
function rgbSplit(_col){
	if (_col.substring(0, 4) === "rgb("){_col = _col.slice(4, -1)}
	else {_col = _col.slice(5, -1)}
	var _ret = _col.split(", ");
	return (_ret);
}


// ================≪ 白・黒の範囲を与えてフィルタを作成 ≫================
function createFilter(_w, _b){
	var br = _b[0], wr = _w[0], wg = _w[1], wb = _w[2];
	var tr = wr - br;
	var r = tr / (255 - tr) * br + br*1;
	var a = br/ r;	// 中心値 r が気をつけないと 0 や 255 になって 0 除算になる
	if (isNaN(a) === true){a = (wr-255) / (r-255);}

	var g = r - (wr - wg) / a;
	var b = r - (wr - wb) / a;
	
	// r, g, b, a, rgba の値を配列で返す
	return ([r, g, b, a, "rgba(" + Math.floor(r) + ", " + Math.floor(g) + ", " + Math.floor(b) + ", " + a + ")"]);
}

// ================≪ フラッシュにもフィルタを適用 ≫================
function flashMode(){
	
	 for (var objs = document.getElementsByTagName("object"), i = 0, obj; obj = objs[i]; i++){
	 
        if (obj.type === "application/x-shockwave-flash"){
            var skip = false;
			obj.style.display = "none";

            for (var params = obj.getElementsByTagName("param"), j = 0, param; param = params[j]; j++){
			
                if (param.getAttribute("name") == "wmode"){
                    skip = true;
                    param.setAttribute("value", "transparent");
					
					// バックグラウンドのフラッシュはこうすると適用される
					_win.setTimeout(function(o){
						o.parentNode.insertBefore(o,o.nextSibling);
						o.style.display = "block";
					}, 100, obj);
					
                    break;
                }
            }
            if(skip != true) {
				// paramが存在しないとき用(動作未確認)
				var param = document.createElement("param");
				param.setAttribute("name", "wmode");
				param.setAttribute("value", "transparent");
				obj.appendChild(param);
				obj.parentNode.insertBefore(obj,obj.nextSibling);
			}
			
			// バックグラウンドのフラッシュはこうすると適用される
			_win.setTimeout(function(o){
				o.parentNode.insertBefore(o,o.nextSibling);
				o.style.display = "block";
			}, 100, obj);
        }
	}
	
	// ----------------< embedタグ >----------------
	for (var embs = document.getElementsByTagName("embed"), i = 0, emb; emb = embs[i]; i++){
		emb.style.display = "none";
		emb.setAttribute("wmode", "transparent");
	
		// バックグラウンドのフラッシュはこうすると適用される
		setTimeout(function(o){
			o.parentNode.insertBefore(o,o.nextSibling);
			o.style.display = "block";
		}, 100, emb);
	}
}