-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathindex.html
279 lines (258 loc) · 13.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
<html>
<head>
<style type="text/css">
#outputDiv canvas {
width: 100%;
height: 100%;
}
.container {
display: table;
width:100%;
height:100%
}
.container div {
display: table-row;
}
#dropNotification {
position: absolute;
top:100px;
left: 20px;
right:20px;
text-align:center;
pointer-events: none;
}
.boxed {
background-color: white;
box-shadow: 5px 5px 2px #999999;
border: 1px solid black;
border-radius: 10px;
}
#aboutBox {
position:absolute;
top:50px;
left: 25%;
width: 50%;
padding-left: 20px;
padding-right: 20px;
}
</style>
<script src='https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js'></script>
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css'/>
</head>
<body>
<div id="aboutBox" class="boxed">
<a href="https://github.com/MaPePeR/jsColorblindSimulator"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"></a>
<h1>jsColorblindSimulator</h1>
<h2>Usage</h2>
<p>Use the file selector in the top left, <strong>drag and drop</strong> or <strong>paste</strong> an image here to load it. You will then be able to choose between different simulations for different kinds of color-blindness.</p>
<p>All processing is done locally in your web browser. The image will not leave your computer.</p>
<p>The displayed image can be moved by clicking and dragging and zoomed by (shift-)double clicking or using the mouse wheel.</p>
<p>The lens-feature allows you to see what the original image looked like in the region around your cursor. The inverse lens shows you the original image and the simulated image around your cursor.</p>
<h2>Uses algorithms from </h2>
<ul>
<li><a href="http://web.archive.org/web/20081014161121/http://www.colorjack.com/labs/colormatrix/" target="blank">http://www.colorjack.com/labs/colormatrix/</a> (web.archive link, because original source is gone)</li>
<li><a href="http://web.archive.org/web/20090318054431/http://www.nofunc.com/Color_Blindness_Library" target="blank">http://www.nofunc.com/Color_Blindness_Library</a> (web.archive link, because original source is gone)</li>
<li><a href="https://daltonlens.org#libdaltonlens" target="blank">libDaltonLens</a> (implementation of <a href="http://vision.psychol.cam.ac.uk/jdmollon/papers/Dichromatsimulation.pdf"><i>Computerized simulation of color appearance for dichromats</i></a> by Brettel et al. 1997)</li>
<li>
Implementation of <a href="https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html" target="_blank"><i>A Physiologically-based Model for Simulation of Color Vision Deficiency</i></a> by Machado et al.
<br>
<small>
<strong>Note:</strong> Previous versions generated wrong results for this algorithm because of an <a href="https://github.com/MaPePeR/jsColorblindSimulator/issues/3" target="_blank">implementation error</a>.
</small>
</li>
</ul>
<h3>The first two algorithms have not been proven to be accurate.</h3>
<a href="http://kaioa.com/node/75#comment-247" target="blank">Comment</a> about the first algorithm:
<blockquote>
<p>You're right, the ColorMatrix version is very simplified, and not accurate. I created that color matrix one night (<a href="http://www.colorjack.com/labs/colormatrix/" target="blank">http://www.colorjack.com/labs/colormatrix/</a>) and since then it's shown up many places... I should probably take that page down before it spreads more! Anyways, it gives you an idea of what it might look like, but for the real thing...</p>
<p>As far as a simple script to simulate color blindness, this one does the best job:</p>
<p><a href="http://www.nofunc.com/Color_Blindness_Library/" target="blank">http://www.nofunc.com/Color_Blindness_Library/</a> - It uses "confusion lines" within the XYZ color space to calculate values (this one is in Javascript, and should be easy to convert to python).</p>
<p>There are a few other methods, and no one really knows exactly what it would look like... these are all generalizations of a small sample, set against the masses.</p>
</blockquote>
Copyright Notice for the second non-commercial algorithm:
<blockquote><pre>
The Color Blind Simulation function is
copyright (c) 2000-2001 by Matthew Wickline and the
Human-Computer Interaction Resource Network ( http://hcirn.com/ ).
It is used with the permission of Matthew Wickline and HCIRN,
and is freely available for non-commercial use. For commercial use, please
contact the Human-Computer Interaction Resource Network ( http://hcirn.com/ ).
</pre></blockquote>
Comment about the third algorithm:
<blockquote><p>
The Brettel et al. method was published in 1997 in the age of CRT monitors and has been adapted to modern sRGB monitors. It should be pretty accurate, at least for full dichromacy. Of course it is still an approximation and many factors make it imperfect, including an uncalibrated monitor, unknown lighting environment, and per-individual variations. In general it will tend to be accurate for small or thin objects (small dots, lines) and too strong for large bright areas, even for full dichromats.
</p></blockquote>
</div>
<div class="container" style="">
<div>
<input type="file" id="fileInput"/>
<label><input type="radio" name="colorblindType" value="Normal" checked/>Normal</label>
<label><input type="radio" name="colorblindType" value="Protanopia"/>Protanopia</label>
<label><input type="radio" name="colorblindType" value="Protanomaly"/>Protanomaly</label>
<label><input type="radio" name="colorblindType" value="Deuteranopia"/>Deuteranopia</label>
<label><input type="radio" name="colorblindType" value="Deuteranomaly"/>Deuteranomaly</label>
<label><input type="radio" name="colorblindType" value="Tritanopia"/>Tritanopia</label>
<label><input type="radio" name="colorblindType" value="Tritanomaly"/>Tritanomaly</label>
<label><input type="radio" name="colorblindType" value="Achromatopsia"/>Achromatopsia</label>
<a href="https://www.youtube.com/watch?v=kYZ00B5O_VQ" target="_blank"><input type="radio" name="colorblindType" value="Achromatomaly" disabled/>Achromatomaly</a>
<label style="margin-left: 1em;display: none;">Severity:<input type="range" min="0" max="100" value="50" class="slider" id="severity"></label>
<select id="method">
<option value="simpl">Simple (ColorMatrix)</option>
<option value="hcirn">Non-commercial-only (HCIRN)</option>
<option value="brett" selected>Accurate (Brettel et al. 1997)</option>
<option value="macha">Accurate (Machado et al. 2009)</option>
</select>
<br/>
<label><input type="radio" name="lens" value="No" checked/>No Lens</label>
<label><input type="radio" name="lens" value="Normal"/>Normal Lens</label>
<label><input type="radio" name="lens" value="Inverse"/>Inverse Lens</label>
<a href="#" onclick="panZoomImage.translateX=0;panZoomImage.translateY=0;panZoomImage.scale=1;panZoomImage.redraw();">Reset View</a>
<a href="#" target="blank" id="imageLink" style="display: none">Open simulated image in new window</a>
<span id="loadingIndicator" style="display:none"> Computing...</span>
</div>
<div>
<hr/>
</div>
<div style="height: 100%" id="canvasDiv">
<div id="dropNotification" class="boxed" style="display: none"><h1>Drop your image to load it</h1></div>
<canvas id="outCanvas">Your Browser does not support <canvas>. Get an upgrade!</canvas>
</div>
</div>
<script src="panZoomImage.js"></script>
<script src="brettel_colorblind_simulation.js"></script>
<script src="hcirn_colorblind_simulation.js"></script>
<script src="machado_colorblind_simulation.js"></script>
<script src="colorblind.js"></script>
<script type="text/javascript">
var loadingIndicator = document.getElementById('loadingIndicator');
function filterOrImageChanged() {
var type = document.querySelector('input[name = "colorblindType"]:checked').value;
var method = document.querySelector('#method option:checked').value;
var filterName = method + type;
console.log("filterOrImageChanged: " + filterName);
document.getElementById('imageLink').style.display = type === "Normal" ? "none" : "inline";
var isMachado = method == "macha";
document.getElementById('severity').parentElement.style.display = isMachado ? 'inline' : 'none';
['Protanopia', 'Deuteranopia', 'Tritanopia', 'Achromatopsia', 'Achromatomaly'].forEach((item, i) => {
document.querySelector('input[type="radio"][value="' + item + '"]').parentElement.style.display = isMachado ? 'none' : 'inline';
});
if (method == 'macha' && type != "Normal") {
filterName += "_" + document.getElementById('severity').value
}
if (currentImage) {
loadingIndicator.style.display="inline";
NProgress.set(0.2);
setTimeout(function () {
getFilteredImage(currentImage, filterName, function (filteredImage, url) {
document.getElementById('imageLink').href = url;
panZoomImage.displayImage(filteredImage);
NProgress.done();
loadingIndicator.style.display="none";
});
}, 0);
}
}
function lensChanged() {
var v = document.querySelector('input[name = "lens"]:checked').value;
if (v === "No") {
panZoomImage.lens = 0;
} else if (v === "Normal") {
panZoomImage.lens = 1;
} else if (v === "Inverse") {
panZoomImage.lens = 2;
} else {
throw "Illegal Lens Type";
}
panZoomImage.redraw();
}
(function() {
var radios = document.querySelectorAll('input[name = "colorblindType"]');
var i;
for (i = 0; i < radios.length; i++) {
radios[i].onclick = filterOrImageChanged;
}
radios = document.querySelectorAll('input[name = "lens"]');
for (i = 0; i < radios.length; i++) {
radios[i].onclick = lensChanged;
}
document.getElementById("method").onchange = filterOrImageChanged;
document.getElementById("severity").onchange = filterOrImageChanged;
})();
//Based on http://stackoverflow.com/a/3814285/2256700
var fileInput = document.getElementById('fileInput');
var currentImage;
fileInput.onchange = function (evt) {
var tgt = evt.target || window.event.srcElement,
files = tgt.files;
readFile(files);
};
function readFile(files) {
document.getElementById("aboutBox").style.display = "none";
// FileReader support
if (FileReader && files && files.length) {
if (files.length !== 1) {
alert("Can only show one file at a time");
return;
}
if (!files[0].type.match('image.*')) {
alert("Was not an image file. :(");
return;
}
NProgress.set(0.0);
var fr = new FileReader();
fr.onload = function () {
var img = new Image();
img.onload = function () {
//createFilteredImage(this);
currentImage = this;
panZoomImage.setHiddenLensImage(currentImage);
clearImageCache();
filterOrImageChanged();
};
img.src = fr.result;
};
fr.readAsDataURL(files[0]);
}
// Not supported
else {
alert("Your Browser does not support the required Features.");
}
}
var canvasDiv = document.getElementById("canvasDiv");
var dropNotification = document.getElementById("dropNotification");
// Based on http://www.html5rocks.com/en/tutorials/file/dndfiles/
canvasDiv.addEventListener('drop', function (evt) {
evt.stopPropagation();
evt.preventDefault();
dropNotification.style.display = "none";
readFile(evt.dataTransfer.files);
}, false);
canvasDiv.addEventListener('dragover', function (evt) {
document.getElementById("aboutBox").style.display = "none";
evt.stopPropagation();
evt.preventDefault();
dropNotification.style.display = "block";
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}, false);
canvasDiv.addEventListener('dragleave', function (evt) {
dropNotification.style.display = "none";
}, false);
//Retrieve Image from Clipboard: http://stackoverflow.com/a/15369753/2256700
document.onpaste = function (event) {
// use event.originalEvent.clipboard for newer chrome versions
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
// find pasted image among pasted items
var blob = null;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") === 0) {
blob = items[i].getAsFile();
}
}
// load image if there is a pasted image
if (blob !== null) {
readFile([blob]);
}
};
</script>
</body>
</html>