// ==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);
}
}