1
0
Fork 0
mirror of https://github.com/kkapsner/CanvasBlocker synced 2025-07-04 12:36:37 +02:00

Added setting "ignoreFrequentColors"

This commit is contained in:
kkapsner 2017-08-07 21:03:34 +02:00
parent 9da251b14d
commit 1733be23f2
8 changed files with 131 additions and 7 deletions

80
lib/colorStatistics.js Normal file
View file

@ -0,0 +1,80 @@
/* jslint moz: true */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
window.scope.colorStatistics = {};
scope = window.scope.colorStatistics;
}
class Statistic{
constructor(){
this.colors = Object.create(null);
this.numberOfColors = 0;
this.minBoundary = {count: Number.NEGATIVE_INFINITY};
this.maxBoundary = {count: Number.POSITIVE_INFINITY, previousColor: this.minBoundary};
this.minBoundary.nextColor = this.maxBoundary;
}
addColor(r, g, b, a){
var index = String.fromCharCode(r, g, b, a);
var color = this.colors[index];
if (!color){
color = {index, color: [r, g, b, a], count: 0, previousColor: this.minBoundary, nextColor: this.minBoundary.nextColor};
this.numberOfColors += 1;
this.minBoundary.nextColor = color;
color.nextColor.previousColor = color;
this.colors[index] = color;
}
color.count += 1;
if (color.count > color.nextColor.count){
// swap colors to remain in right order
// a -> b -> c -> d becomes a -> c -> b -> d
var a = color.previousColor;
var b = color;
var c = color.nextColor;
var d = color.nextColor.nextColor;
a.nextColor = c;
c.previousColor = a;
c.nextColor = b;
b.previousColor = c;
b.nextColor = d;
d.previousColor = b;
}
}
getMaxColors(n){
var n = Math.min(n, this.numberOfColors);
var colors = Object.create(null);
var current = this.maxBoundary;
for (;n && current;n -= 1){
current = current.previousColor;
colors[current.index] = current;
}
return colors;
}
}
scope.compute = function computeColorStatistics(rawData){
var statistic = new Statistic();
for (var i = 0, l = rawData.length; i < l; i += 4){
statistic.addColor(
rawData[i + 0],
rawData[i + 1],
rawData[i + 2],
rawData[i + 3]
);
}
return statistic;
}
}());

View file

@ -8,6 +8,7 @@ var settings = {
minFakeSize: 1,
maxFakeSize: 0,
rng: "constant",
ignoreFrequentColors: 0,
persistentRndStorage: "",
storePersistentRnd: false,
askOnlyOnce: true,

View file

@ -14,6 +14,8 @@
scope = window.scope.modifiedAPI;
}
const colorStatistics = require("./colorStatistics");
// let Cu = require("chrome").Cu;
var randomSupply = null;
@ -52,7 +54,7 @@
};
}
function getFakeCanvas(window, original){
function getFakeCanvas(window, original, prefs){
try {
// original may not be a canvas -> we must not leak an error
var context = getContext(window, original);
@ -61,6 +63,11 @@
var l = desc.length;
var ignoredColors = {};
if (prefs("ignoreFrequentColors")){
var statistic = colorStatistics.compute(source);
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
}
var rng = randomSupply.getPixelRng(l, window, ignoredColors);
for (var i = 0; i < l; i += 4){
@ -175,7 +182,7 @@
return function toDataURL(){
if (canvasSizeShouldBeFaked(this, prefs)){
notify.call(this, "fakedReadout");
return original.apply(getFakeCanvas(window, this), window.Array.from(arguments));
return original.apply(getFakeCanvas(window, this, prefs), window.Array.from(arguments));
}
else {
return original.apply(this, window.Array.from(arguments));
@ -201,7 +208,7 @@
return function toBlob(callback){
if (canvasSizeShouldBeFaked(this, prefs)){
notify.call(this, "fakedReadout");
return original.apply(getFakeCanvas(window, this), window.Array.from(arguments));
return original.apply(getFakeCanvas(window, this, prefs), window.Array.from(arguments));
}
else {
return original.apply(this, window.Array.from(arguments));
@ -228,7 +235,7 @@
return function mozGetAsFile(callback){
if (canvasSizeShouldBeFaked(this, prefs)){
notify.call(this, "fakedReadout");
return original.apply(getFakeCanvas(window, this), window.Array.from(arguments));
return original.apply(getFakeCanvas(window, this, prefs), window.Array.from(arguments));
}
else {
return original.apply(this, window.Array.from(arguments));
@ -257,11 +264,11 @@
var fakeCanvas;
var context = this;
if (this && this.canvas) {
fakeCanvas = getFakeCanvas(window, this.canvas);
fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
}
if (fakeCanvas && fakeCanvas !== this.canvas){
context = window.HTMLCanvasElement.prototype.getContext.call(
getFakeCanvas(window, this.canvas),
fakeCanvas,
"2d"
);
}
@ -349,7 +356,12 @@
var xPixels = pixels;
var ret = original.apply(this, window.Array.from(arguments));
var l = xPixels.length;
var rng = randomSupply.getPixelRng(l, window, {});
var ignoredColors = {};
if (prefs("ignoreFrequentColors")){
var statistic = colorStatistics.compute(pixels);
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
}
var rng = randomSupply.getPixelRng(l, window, ignoredColors);
for (var i = 0; i < l; i += 4){
var [r, g, b, a] = rng(