diva.js 6.0.1 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.clang-format +7 -0
- package/.github/workflows/npm-publish.yml +45 -0
- package/LICENSE +55 -0
- package/Makefile +75 -0
- package/README.md +15 -108
- package/elm.json +32 -0
- package/package.json +12 -59
- package/review/elm.json +52 -0
- package/review/src/ReviewConfig.elm +87 -0
- package/scripts/elm-esm.sh +40 -0
- package/scripts/minify-css.mjs +31 -0
- package/src/Filters.elm +1044 -0
- package/src/Main.elm +1217 -0
- package/src/Model.elm +213 -0
- package/src/Msg.elm +59 -0
- package/src/Utilities.elm +46 -0
- package/src/View/CollectionExplorer.elm +172 -0
- package/src/View/Helpers.elm +86 -0
- package/src/View/HtmlRenderer.elm +136 -0
- package/src/View/Icons.elm +159 -0
- package/src/View/ManifestInfoModal.elm +363 -0
- package/src/View/PageViewModal.elm +1046 -0
- package/src/View/Sidebar.elm +786 -0
- package/src/View/Toolbar.elm +189 -0
- package/src/View.elm +244 -0
- package/src/diva.ts +802 -0
- package/src/filters.ts +1843 -0
- package/src/styles/app.css +328 -0
- package/src/styles/collection.css +75 -0
- package/src/styles/modal.css +388 -0
- package/src/styles/sidebar.css +215 -0
- package/src/styles/theme.css +39 -0
- package/src/styles/toolbar.css +154 -0
- package/src/viewer-element.ts +1307 -0
- package/testing/index.html +52 -0
- package/testing/testing.html +231 -0
- package/tsconfig.json +12 -0
- package/AUTHORS +0 -22
- package/_site/diva.iml +0 -11
- package/build/diva.css +0 -554
- package/build/diva.css.map +0 -1
- package/build/diva.js +0 -9
- package/build/diva.js.map +0 -1
- package/build/plugins/download.js +0 -2
- package/build/plugins/download.js.map +0 -1
- package/build/plugins/manipulation.js +0 -2
- package/build/plugins/manipulation.js.map +0 -1
- package/build/plugins/metadata.js +0 -2
- package/build/plugins/metadata.js.map +0 -1
- package/diva.iml +0 -11
- package/index.html +0 -28
- package/karma.conf.js +0 -87
- package/source/css/_mixins.scss +0 -43
- package/source/css/_variables.scss +0 -50
- package/source/css/_viewer.scss +0 -462
- package/source/css/diva.scss +0 -15
- package/source/css/plugins/_manipulation.scss +0 -228
- package/source/css/plugins/_metadata.scss +0 -31
- package/source/img/adjust.svg +0 -11
- package/source/img/book-view.svg +0 -6
- package/source/img/close.svg +0 -6
- package/source/img/download.svg +0 -6
- package/source/img/from-fullscreen.svg +0 -8
- package/source/img/grid-fewer.svg +0 -6
- package/source/img/grid-more.svg +0 -6
- package/source/img/grid-view.svg +0 -6
- package/source/img/link.svg +0 -6
- package/source/img/metadata.svg +0 -9
- package/source/img/page-view.svg +0 -6
- package/source/img/to-fullscreen.svg +0 -11
- package/source/img/zoom-in.svg +0 -6
- package/source/img/zoom-out.svg +0 -7
- package/source/js/composite-image.js +0 -174
- package/source/js/diva-global.js +0 -7
- package/source/js/diva.js +0 -1543
- package/source/js/document-handler.js +0 -180
- package/source/js/document-layout.js +0 -286
- package/source/js/exceptions.js +0 -26
- package/source/js/gesture-events.js +0 -190
- package/source/js/grid-handler.js +0 -122
- package/source/js/iiif-source-adapter.js +0 -63
- package/source/js/image-cache.js +0 -113
- package/source/js/image-manifest.js +0 -157
- package/source/js/image-request-handler.js +0 -76
- package/source/js/interpolate-animation.js +0 -122
- package/source/js/page-layouts/book-layout.js +0 -161
- package/source/js/page-layouts/grid-layout.js +0 -97
- package/source/js/page-layouts/index.js +0 -38
- package/source/js/page-layouts/page-dimensions.js +0 -9
- package/source/js/page-layouts/singles-layout.js +0 -27
- package/source/js/page-overlay-manager.js +0 -102
- package/source/js/page-tools-overlay.js +0 -95
- package/source/js/parse-iiif-manifest.js +0 -302
- package/source/js/plugins/_filters.js +0 -679
- package/source/js/plugins/download.js +0 -83
- package/source/js/plugins/manipulation.js +0 -837
- package/source/js/plugins/metadata.js +0 -190
- package/source/js/renderer.js +0 -584
- package/source/js/settings-view.js +0 -30
- package/source/js/tile-coverage-map.js +0 -25
- package/source/js/toolbar.js +0 -572
- package/source/js/utils/dragscroll.js +0 -106
- package/source/js/utils/elt.js +0 -94
- package/source/js/utils/events.js +0 -190
- package/source/js/utils/get-scrollbar-width.js +0 -29
- package/source/js/utils/hash-params.js +0 -86
- package/source/js/utils/parse-label-value.js +0 -34
- package/source/js/utils/vanilla.kinetic.js +0 -527
- package/source/js/validation-runner.js +0 -177
- package/source/js/viewer-core.js +0 -1505
- package/source/js/viewport.js +0 -143
- package/test/_setup.js +0 -13
- package/test/composite-image_test.js +0 -94
- package/test/diva_test.js +0 -43
- package/test/hash-params_test.js +0 -221
- package/test/image-cache_test.js +0 -106
- package/test/main.js +0 -6
- package/test/manifests/beromunsterManifest.json +0 -15514
- package/test/manifests/iiifv2.json +0 -11032
- package/test/manifests/iiifv2pages.json +0 -30437
- package/test/manifests/iiifv3.json +0 -10965
- package/test/navigation_test.js +0 -355
- package/test/parse-iiif-manifest_test.js +0 -68
- package/test/public_test.js +0 -881
- package/test/settings_test.js +0 -487
- package/test/utils/book-layout_test.js +0 -148
- package/test/utils/elt_test.js +0 -102
- package/test/utils/events_test.js +0 -245
- package/test/utils/hash-params_test.js +0 -79
- package/test/utils/parse-label-value_test.js +0 -45
- package/test/z_plugins_test.js +0 -180
- package/webpack.config.js +0 -58
- package/webpack.config.test.js +0 -45
|
@@ -1,679 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
// stores an array of objects, each object stores the function, image data, adjust to apply, and name
|
|
3
|
-
let _filterQueue = [];
|
|
4
|
-
// stores whether the invert filter was used (for if it should be reapplied)
|
|
5
|
-
let inverted = false;
|
|
6
|
-
|
|
7
|
-
export function resetFilters ()
|
|
8
|
-
{
|
|
9
|
-
_filterQueue = [];
|
|
10
|
-
inverted = false;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Add a filter to the array. If it is new, apply the filter's function to the image data of
|
|
14
|
-
// the previous filter's returned image data (or the default image data if it's the first filter),
|
|
15
|
-
// and return this new image data. Pass string 'name' since function.name with minifiedJS = bad
|
|
16
|
-
// Threshold is exclusive to other filters and vice versa
|
|
17
|
-
export function addFilterToQueue (data, filter, adjust, name)
|
|
18
|
-
{
|
|
19
|
-
// index of the filter in the queue, -1 if not found
|
|
20
|
-
let index = _filterQueue.findIndex(f => f.filter.name === filter.name);
|
|
21
|
-
if (index !== -1) // adjust a filter already in the queue
|
|
22
|
-
{
|
|
23
|
-
let filtObj = _filterQueue[index];
|
|
24
|
-
filtObj.adjust = adjust;
|
|
25
|
-
|
|
26
|
-
// all filters except sharpness use _apply (from within their private function 'filter')
|
|
27
|
-
// whereas sharpness uses convolve, so need to check (ie. can't generalize for all filters)
|
|
28
|
-
if (filtObj.name === 'Sharpness')
|
|
29
|
-
{
|
|
30
|
-
// if adjust[1] is 0, then sharpness should be reset (cancelled)
|
|
31
|
-
if (filtObj.adjust[1] === 0)
|
|
32
|
-
filtObj.postData = filtObj.prevData;
|
|
33
|
-
else
|
|
34
|
-
filtObj.postData = convolve(filtObj.prevData, filtObj.adjust);
|
|
35
|
-
}
|
|
36
|
-
else if (filtObj.name === 'Invert')
|
|
37
|
-
{
|
|
38
|
-
// invert filter should toggle, so use post-alteration image data
|
|
39
|
-
filtObj.postData = _apply(filtObj.postData, filtObj.filter, filtObj.adjust);
|
|
40
|
-
inverted = !inverted;
|
|
41
|
-
}
|
|
42
|
-
else
|
|
43
|
-
filtObj.postData = _apply(filtObj.prevData, filtObj.filter, filtObj.adjust);
|
|
44
|
-
|
|
45
|
-
// reapply all filters that come after in the queue
|
|
46
|
-
for (let i = index + 1, len = _filterQueue.length; i < len; i++)
|
|
47
|
-
{
|
|
48
|
-
let otherFiltObj = _filterQueue[i];
|
|
49
|
-
|
|
50
|
-
if (otherFiltObj.name === 'Invert' && !inverted) // don't reinvert the image
|
|
51
|
-
continue;
|
|
52
|
-
|
|
53
|
-
otherFiltObj.prevData = _filterQueue[i - 1].postData; // starts at filt
|
|
54
|
-
|
|
55
|
-
if (otherFiltObj.name === 'Sharpness')
|
|
56
|
-
if (otherFiltObj.adjust[1] === 0)
|
|
57
|
-
otherFiltObj.postData = otherFiltObj.prevData;
|
|
58
|
-
else
|
|
59
|
-
otherFiltObj.postData = convolve(otherFiltObj.prevData, otherFiltObj.adjust);
|
|
60
|
-
else
|
|
61
|
-
otherFiltObj.postData = _apply(otherFiltObj.prevData, otherFiltObj.filter, otherFiltObj.adjust);
|
|
62
|
-
|
|
63
|
-
if (i === len - 1) // last filter
|
|
64
|
-
return otherFiltObj.postData;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// only two filters in queue and second was modified
|
|
68
|
-
return filtObj.postData;
|
|
69
|
-
}
|
|
70
|
-
else // add new filter to the queue
|
|
71
|
-
{
|
|
72
|
-
// handle threshold uniqueness
|
|
73
|
-
if (name === 'Threshold' || (_filterQueue[0] && _filterQueue[0].name === 'Threshold'))
|
|
74
|
-
{
|
|
75
|
-
// reset filter queue
|
|
76
|
-
resetFilters();
|
|
77
|
-
|
|
78
|
-
// reset appropriate sliders
|
|
79
|
-
let tools = document.getElementsByClassName('manipulation-tools')[0];
|
|
80
|
-
for (let i = 0, len = tools.children.length; i < len; i++)
|
|
81
|
-
{
|
|
82
|
-
let tool = tools.children[i].children[0];
|
|
83
|
-
|
|
84
|
-
if (tool && tool.type === 'range')
|
|
85
|
-
{
|
|
86
|
-
let isThreshold = tool.parentElement.textContent.includes('Threshold');
|
|
87
|
-
let isZoom = tool.parentElement.textContent.includes('Zoom');
|
|
88
|
-
let isRotate = tool.parentElement.textContent.includes('Rotation');
|
|
89
|
-
|
|
90
|
-
if (name === 'Threshold' && !isThreshold && !isZoom && !isRotate) // reset all except
|
|
91
|
-
tool.value = 0;
|
|
92
|
-
else if (name !== 'Threshold' && isThreshold) // reset only threshold
|
|
93
|
-
tool.value = 0;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// reset log
|
|
98
|
-
document.getElementById('filter-log').innerHTML = "<h3> Filter Application Order <h3>";
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
_filterQueue.push({
|
|
102
|
-
filter: filter,
|
|
103
|
-
prevData: _filterQueue.length === 0 ? data : _filterQueue[_filterQueue.length - 1].postData,
|
|
104
|
-
adjust: adjust,
|
|
105
|
-
name: name
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
let filtObj = _filterQueue[_filterQueue.length - 1];
|
|
109
|
-
|
|
110
|
-
if (filtObj.name === 'Sharpness')
|
|
111
|
-
filtObj.postData = convolve(filtObj.prevData, filtObj.adjust);
|
|
112
|
-
else
|
|
113
|
-
filtObj.postData = _apply(filtObj.prevData, filtObj.filter, filtObj.adjust);
|
|
114
|
-
|
|
115
|
-
// invert filter was added to queue
|
|
116
|
-
if (filtObj.name === 'Invert')
|
|
117
|
-
inverted = true;
|
|
118
|
-
|
|
119
|
-
// add name to applied filters log
|
|
120
|
-
let p = document.createElement('p');
|
|
121
|
-
p.setAttribute('style', 'color: white; margin: 0;');
|
|
122
|
-
p.innerText = filtObj.name;
|
|
123
|
-
document.getElementById('filter-log').appendChild(p);
|
|
124
|
-
|
|
125
|
-
return filtObj.postData;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Pre-paints the adjustment to an offscreen canvas before moving it to the on-screen canvas.
|
|
131
|
-
**/
|
|
132
|
-
function _getOffscreenCanvasData (w, h)
|
|
133
|
-
{
|
|
134
|
-
let tmpCanvas = document.createElement('canvas');
|
|
135
|
-
let tmpCtx = tmpCanvas.getContext('2d');
|
|
136
|
-
|
|
137
|
-
return tmpCtx.createImageData(w, h);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function _manipulateImage (data, func, adjustment)
|
|
141
|
-
{
|
|
142
|
-
let len = data.length;
|
|
143
|
-
|
|
144
|
-
for (let i = 0; i < len; i += 4)
|
|
145
|
-
{
|
|
146
|
-
let r = data[i];
|
|
147
|
-
let g = data[i + 1];
|
|
148
|
-
let b = data[i + 2];
|
|
149
|
-
|
|
150
|
-
let newPixelValue = func(r, g, b, adjustment);
|
|
151
|
-
|
|
152
|
-
data[i] = newPixelValue[0];
|
|
153
|
-
data[i + 1] = newPixelValue[1];
|
|
154
|
-
data[i + 2] = newPixelValue[2];
|
|
155
|
-
data[i + 3] = newPixelValue[3];
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return data;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function _apply (data, pixelFunc, adjust)
|
|
162
|
-
{
|
|
163
|
-
let dataArr = new Uint8ClampedArray(data.data);
|
|
164
|
-
let inverted = _manipulateImage(dataArr, pixelFunc, adjust);
|
|
165
|
-
|
|
166
|
-
let newCanvasData = _getOffscreenCanvasData(data.width, data.height);
|
|
167
|
-
newCanvasData.data.set(inverted);
|
|
168
|
-
|
|
169
|
-
return newCanvasData;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Inverts the colours of a canvas.
|
|
174
|
-
*
|
|
175
|
-
* @params {object} data - A canvas image data object.
|
|
176
|
-
* @returns {object} A new canvas data object.
|
|
177
|
-
**/
|
|
178
|
-
export function grayscale(data)
|
|
179
|
-
{
|
|
180
|
-
return addFilterToQueue(data, _grayscale, null, 'Grayscale');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* See: https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
|
|
185
|
-
*
|
|
186
|
-
* Reference: http://www.phpied.com/image-fun/ and https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L89
|
|
187
|
-
*
|
|
188
|
-
* @params {integer} r - the value of the red pixel
|
|
189
|
-
* @params {integer} g - the value of the green pixel
|
|
190
|
-
* @params {integer} b - the value of the blue pixel
|
|
191
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
192
|
-
**/
|
|
193
|
-
function _grayscale (r, g, b)
|
|
194
|
-
{
|
|
195
|
-
let pixelAverage = (0.3 * r + 0.59 * g + 0.11 * b);
|
|
196
|
-
|
|
197
|
-
return [pixelAverage, pixelAverage, pixelAverage, 255];
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export function saturation (data, adjust)
|
|
201
|
-
{
|
|
202
|
-
return addFilterToQueue(data, _saturation, adjust, 'Saturation');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Adjusts the color saturation of the image.
|
|
207
|
-
* Range is -100 to 100. Values < 0 will desaturate the image while values > 0 will saturate it.
|
|
208
|
-
*
|
|
209
|
-
* See https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L42-L58
|
|
210
|
-
*
|
|
211
|
-
* @params {integer} r - the value of the red pixel
|
|
212
|
-
* @params {integer} g - the value of the green pixel
|
|
213
|
-
* @params {integer} b - the value of the blue pixel
|
|
214
|
-
* @params {integer} adjust - the saturation value for adjustment, -100 to 100
|
|
215
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
216
|
-
**/
|
|
217
|
-
function _saturation (r, g, b, adjust)
|
|
218
|
-
{
|
|
219
|
-
let adj = adjust * -0.01;
|
|
220
|
-
let max = Math.max(r, g, b);
|
|
221
|
-
|
|
222
|
-
return [
|
|
223
|
-
r !== max ? r + (max - r) * adj : r,
|
|
224
|
-
g !== max ? g + (max - g) * adj : g,
|
|
225
|
-
b !== max ? b + (max - b) * adj : b,
|
|
226
|
-
255
|
|
227
|
-
];
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export function vibrance (data, adjust)
|
|
231
|
-
{
|
|
232
|
-
return addFilterToQueue(data, _vibrance, adjust, 'Vibrance');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Similar to saturation, but adjusts the saturation levels in a slightly smarter, more subtle way.
|
|
237
|
-
* Vibrance will attempt to boost colors that are less saturated more and boost already saturated
|
|
238
|
-
* colors less, while saturation boosts all colors by the same level.
|
|
239
|
-
*
|
|
240
|
-
* See: https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L60
|
|
241
|
-
*
|
|
242
|
-
* @params {integer} r - the value of the red pixel
|
|
243
|
-
* @params {integer} g - the value of the green pixel
|
|
244
|
-
* @params {integer} b - the value of the blue pixel
|
|
245
|
-
* @params {integer} adjust - the vibrance value for adjustment, -100 to 100
|
|
246
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
247
|
-
**/
|
|
248
|
-
function _vibrance (r, g, b, adjust)
|
|
249
|
-
{
|
|
250
|
-
let adj = adjust * -1;
|
|
251
|
-
|
|
252
|
-
let max = Math.max(r, g, b);
|
|
253
|
-
let avg = r + g + b / 3;
|
|
254
|
-
let amt = ((Math.abs(max - avg) * 2 / 255) * adj) / 100;
|
|
255
|
-
|
|
256
|
-
return [
|
|
257
|
-
r !== max ? r + (max - r) * amt : r,
|
|
258
|
-
g !== max ? g + (max - g) * amt : g,
|
|
259
|
-
b !== max ? b + (max - b) * amt : b,
|
|
260
|
-
255
|
|
261
|
-
];
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export function brightness (data, adjust)
|
|
265
|
-
{
|
|
266
|
-
return addFilterToQueue(data, _brightness, adjust, 'Brightness');
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function _brightness (r, g, b, adjust)
|
|
270
|
-
{
|
|
271
|
-
let adj = Math.floor(255 * (adjust / 100));
|
|
272
|
-
|
|
273
|
-
return [
|
|
274
|
-
r + adj,
|
|
275
|
-
g + adj,
|
|
276
|
-
b + adj,
|
|
277
|
-
255
|
|
278
|
-
];
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export function contrast (data, adjust)
|
|
282
|
-
{
|
|
283
|
-
return addFilterToQueue(data, _contrast, adjust, 'Contrast');
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Increases or decreases the color contrast of the image.
|
|
288
|
-
*
|
|
289
|
-
* @params {integer} r - the value of the red pixel
|
|
290
|
-
* @params {integer} g - the value of the green pixel
|
|
291
|
-
* @params {integer} b - the value of the blue pixel
|
|
292
|
-
* @params {integer} adjust - the contrast value for adjustment, -100 to 100
|
|
293
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
294
|
-
**/
|
|
295
|
-
function _contrast (r, g, b, adjust)
|
|
296
|
-
{
|
|
297
|
-
let adj = Math.pow((adjust + 100) / 100, 2);
|
|
298
|
-
let rr = r, gg = g, bb = b;
|
|
299
|
-
|
|
300
|
-
rr /= 255;
|
|
301
|
-
rr -= 0.5;
|
|
302
|
-
rr *= adj;
|
|
303
|
-
rr += 0.5;
|
|
304
|
-
rr *= 255;
|
|
305
|
-
|
|
306
|
-
gg /= 255;
|
|
307
|
-
gg -= 0.5;
|
|
308
|
-
gg *= adj;
|
|
309
|
-
gg += 0.5;
|
|
310
|
-
gg *= 255;
|
|
311
|
-
|
|
312
|
-
bb /= 255;
|
|
313
|
-
bb -= 0.5;
|
|
314
|
-
bb *= adj;
|
|
315
|
-
bb += 0.5;
|
|
316
|
-
bb *= 255;
|
|
317
|
-
|
|
318
|
-
return [
|
|
319
|
-
rr, gg, bb, 255
|
|
320
|
-
];
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Inverts the colours of a canvas.
|
|
324
|
-
*
|
|
325
|
-
* @params {object} data - A canvas image data object.
|
|
326
|
-
* @returns {object} A new canvas data object.
|
|
327
|
-
**/
|
|
328
|
-
export function invert(data)
|
|
329
|
-
{
|
|
330
|
-
return addFilterToQueue(data, _invert, null, 'Invert');
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Inverts the colours of the image.
|
|
335
|
-
* See: https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L183
|
|
336
|
-
*
|
|
337
|
-
* @params {integer} r - the value of the red pixel
|
|
338
|
-
* @params {integer} g - the value of the green pixel
|
|
339
|
-
* @params {integer} b - the value of the blue pixel
|
|
340
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
341
|
-
**/
|
|
342
|
-
function _invert (r, g, b)
|
|
343
|
-
{
|
|
344
|
-
return [
|
|
345
|
-
255 - r,
|
|
346
|
-
255 - g,
|
|
347
|
-
255 - b,
|
|
348
|
-
255
|
|
349
|
-
];
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export function threshold(data, adjust)
|
|
353
|
-
{
|
|
354
|
-
return addFilterToQueue(data, _threshold, adjust, 'Threshold');
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Black pixels above a certain value (0-255); otherwise white. Perceptively weighted.
|
|
359
|
-
*
|
|
360
|
-
* See: https://www.html5rocks.com/en/tutorials/canvas/imagefilters/
|
|
361
|
-
*
|
|
362
|
-
* @params {integer} r - the value of the red pixel
|
|
363
|
-
* @params {integer} g - the value of the green pixel
|
|
364
|
-
* @params {integer} b - the value of the blue pixel
|
|
365
|
-
* @params {integer} adjust - the threshold value, 0-255
|
|
366
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
367
|
-
**/
|
|
368
|
-
function _threshold (r, g, b, adjust)
|
|
369
|
-
{
|
|
370
|
-
let v = (0.2126 * r + 0.7152 * g + 0.0722 * b >= adjust) ? 255 : 0;
|
|
371
|
-
|
|
372
|
-
return [
|
|
373
|
-
v, v, v, 255
|
|
374
|
-
];
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
export function hue (data, adjust)
|
|
379
|
-
{
|
|
380
|
-
return addFilterToQueue(data, _hue, adjust, 'Hue');
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function _hue (r, g, b, adjust)
|
|
384
|
-
{
|
|
385
|
-
let {h, s, v} = rgbToHSV(r, g, b);
|
|
386
|
-
|
|
387
|
-
h = h * 100;
|
|
388
|
-
h += Math.abs(adjust);
|
|
389
|
-
h = h % 100;
|
|
390
|
-
h /= 100;
|
|
391
|
-
|
|
392
|
-
let res = hsvToRGB(h, s, v);
|
|
393
|
-
|
|
394
|
-
return [
|
|
395
|
-
res.r, res.g, res.b, 255
|
|
396
|
-
];
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export function gamma (data, adjust)
|
|
400
|
-
{
|
|
401
|
-
return addFilterToQueue(data, _gamma, adjust, 'Gamma');
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Adjusts the gamma of the image.
|
|
406
|
-
* Range is 0 to 4. Values between 0 and 1 will lessen the contrast while values greater
|
|
407
|
-
* than 1 will increase it. Starts at 1 default. The actual adjust slider is from -100 to
|
|
408
|
-
* 300 (so default can be 0 and offset accordingly), so must scale properly
|
|
409
|
-
* See https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L210-L221
|
|
410
|
-
*
|
|
411
|
-
* @params {integer} r - the value of the red pixel
|
|
412
|
-
* @params {integer} g - the value of the green pixel
|
|
413
|
-
* @params {integer} b - the value of the blue pixel
|
|
414
|
-
* @params {integer} adjust - the gamma value for adjustment, 0 to 400
|
|
415
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
416
|
-
**/
|
|
417
|
-
function _gamma (r, g, b, adjust)
|
|
418
|
-
{
|
|
419
|
-
let adj = adjust / 100 + 1;
|
|
420
|
-
if (adj < 0)
|
|
421
|
-
adj *= -1;
|
|
422
|
-
|
|
423
|
-
return [
|
|
424
|
-
Math.pow(r / 255, adj) * 255,
|
|
425
|
-
Math.pow(g / 255, adj) * 255,
|
|
426
|
-
Math.pow(b / 255, adj) * 255,
|
|
427
|
-
255
|
|
428
|
-
];
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
export function ccRed (data, adjust)
|
|
432
|
-
{
|
|
433
|
-
return addFilterToQueue(data, _ccRed, adjust, 'CC Red');
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Adjusts the red intensity of the image.
|
|
438
|
-
*
|
|
439
|
-
* See https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L274-L305
|
|
440
|
-
*
|
|
441
|
-
* @params {integer} r - the value of the red pixel
|
|
442
|
-
* @params {integer} g - the value of the green pixel
|
|
443
|
-
* @params {integer} b - the value of the blue pixel
|
|
444
|
-
* @params {integer} adjust - the red value for adjustment, -100 to 100
|
|
445
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
446
|
-
*/
|
|
447
|
-
function _ccRed (r, g, b, adjust)
|
|
448
|
-
{
|
|
449
|
-
let adj = adjust / 100;
|
|
450
|
-
|
|
451
|
-
return [
|
|
452
|
-
adj > 0 ? r + (255 - r) * adj : r - r * Math.abs(adj),
|
|
453
|
-
g,
|
|
454
|
-
b,
|
|
455
|
-
255
|
|
456
|
-
];
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
export function ccGreen (data, adjust)
|
|
460
|
-
{
|
|
461
|
-
return addFilterToQueue(data, _ccGreen, adjust, 'CC Green');
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Adjusts the green intensity of the image.
|
|
466
|
-
*
|
|
467
|
-
* See https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L274-L305
|
|
468
|
-
*
|
|
469
|
-
* @params {integer} r - the value of the red pixel
|
|
470
|
-
* @params {integer} g - the value of the green pixel
|
|
471
|
-
* @params {integer} b - the value of the blue pixel
|
|
472
|
-
* @params {integer} adjust - the green value for adjustment, -100 to 100
|
|
473
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
474
|
-
*/
|
|
475
|
-
function _ccGreen (r, g, b, adjust)
|
|
476
|
-
{
|
|
477
|
-
let adj = adjust / 100;
|
|
478
|
-
|
|
479
|
-
return [
|
|
480
|
-
r,
|
|
481
|
-
adj > 0 ? g + (255 - g) * adj : g - g * Math.abs(adj),
|
|
482
|
-
b,
|
|
483
|
-
255
|
|
484
|
-
];
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
export function ccBlue (data, adjust)
|
|
488
|
-
{
|
|
489
|
-
return addFilterToQueue(data, _ccBlue, adjust, 'CC Blue');
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
/**
|
|
493
|
-
* Adjusts the blue intensity of the image.
|
|
494
|
-
*
|
|
495
|
-
* See https://github.com/meltingice/CamanJS/blob/master/src/lib/filters.coffee#L274-L305
|
|
496
|
-
*
|
|
497
|
-
* @params {integer} r - the value of the red pixel
|
|
498
|
-
* @params {integer} g - the value of the green pixel
|
|
499
|
-
* @params {integer} b - the value of the blue pixel
|
|
500
|
-
* @params {integer} adjust - the blue value for adjustment, -100 to 100
|
|
501
|
-
* @returns {Array} - The computed RGB values for the input, with a constant 255 for the alpha channel.
|
|
502
|
-
*/
|
|
503
|
-
function _ccBlue (r, g, b, adjust)
|
|
504
|
-
{
|
|
505
|
-
let adj = adjust / 100;
|
|
506
|
-
|
|
507
|
-
return [
|
|
508
|
-
r,
|
|
509
|
-
g,
|
|
510
|
-
adj > 0 ? b + (255 - b) * adj : b - b * Math.abs(adj),
|
|
511
|
-
255
|
|
512
|
-
];
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
export function rgbToHSV (r, g, b)
|
|
516
|
-
{
|
|
517
|
-
let rr = r, gg = g, bb = b;
|
|
518
|
-
|
|
519
|
-
rr /= 255;
|
|
520
|
-
gg /= 255;
|
|
521
|
-
bb /= 255;
|
|
522
|
-
|
|
523
|
-
let max = Math.max(rr, gg, bb);
|
|
524
|
-
let min = Math.min(rr, gg, bb);
|
|
525
|
-
let v = max;
|
|
526
|
-
let d = max - min;
|
|
527
|
-
|
|
528
|
-
let s = max === 0 ? 0 : d / max;
|
|
529
|
-
let h;
|
|
530
|
-
|
|
531
|
-
if (max === min)
|
|
532
|
-
h = 0;
|
|
533
|
-
else
|
|
534
|
-
{
|
|
535
|
-
switch (max)
|
|
536
|
-
{
|
|
537
|
-
case rr:
|
|
538
|
-
h = (gg - bb) / d + (gg < bb ? 6 : 0);
|
|
539
|
-
break;
|
|
540
|
-
case gg:
|
|
541
|
-
h = (bb - rr) / d + 2;
|
|
542
|
-
break;
|
|
543
|
-
case bb:
|
|
544
|
-
h = (rr - gg) / d + 4;
|
|
545
|
-
break;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
h /= 6;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
return {h, s, v};
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
export function hsvToRGB (h, s, v)
|
|
555
|
-
{
|
|
556
|
-
let b, f, g, i, p, q, r, t;
|
|
557
|
-
i = Math.floor(h * 6);
|
|
558
|
-
f = h * 6 - i;
|
|
559
|
-
p = v * (1 - s);
|
|
560
|
-
q = v * (1 - f * s);
|
|
561
|
-
t = v * (1 - (1 - f) * s);
|
|
562
|
-
|
|
563
|
-
switch (i % 6)
|
|
564
|
-
{
|
|
565
|
-
case 0:
|
|
566
|
-
r = v;
|
|
567
|
-
g = t;
|
|
568
|
-
b = p;
|
|
569
|
-
break;
|
|
570
|
-
case 1:
|
|
571
|
-
r = q;
|
|
572
|
-
g = v;
|
|
573
|
-
b = p;
|
|
574
|
-
break;
|
|
575
|
-
case 2:
|
|
576
|
-
r = p;
|
|
577
|
-
g = v;
|
|
578
|
-
b = t;
|
|
579
|
-
break;
|
|
580
|
-
case 3:
|
|
581
|
-
r = p;
|
|
582
|
-
g = q;
|
|
583
|
-
b = v;
|
|
584
|
-
break;
|
|
585
|
-
case 4:
|
|
586
|
-
r = t;
|
|
587
|
-
g = p;
|
|
588
|
-
b = v;
|
|
589
|
-
break;
|
|
590
|
-
case 5:
|
|
591
|
-
r = v;
|
|
592
|
-
g = p;
|
|
593
|
-
b = q;
|
|
594
|
-
break;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
return {
|
|
598
|
-
r: Math.floor(r * 255),
|
|
599
|
-
g: Math.floor(g * 255),
|
|
600
|
-
b: Math.floor(b * 255)
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
/*********************************************
|
|
606
|
-
Convolution filters
|
|
607
|
-
*********************************************/
|
|
608
|
-
|
|
609
|
-
function convolve (data, weights, opaque)
|
|
610
|
-
{
|
|
611
|
-
let side = Math.round(Math.sqrt(weights.length));
|
|
612
|
-
let halfSide = Math.floor(side / 2);
|
|
613
|
-
|
|
614
|
-
let srcData = data.data;
|
|
615
|
-
let sw = data.width;
|
|
616
|
-
let sh = data.height;
|
|
617
|
-
let w = sw;
|
|
618
|
-
let h = sh;
|
|
619
|
-
|
|
620
|
-
let output = _getOffscreenCanvasData(w, h);
|
|
621
|
-
let dst = output.data;
|
|
622
|
-
|
|
623
|
-
let alphaFac = opaque ? 1 : 0;
|
|
624
|
-
|
|
625
|
-
for (let y = 0; y < h; y++)
|
|
626
|
-
{
|
|
627
|
-
for (let x = 0; x < w; x++)
|
|
628
|
-
{
|
|
629
|
-
let sy = y;
|
|
630
|
-
let sx = x;
|
|
631
|
-
let dstOff = (y * w + x) * 4;
|
|
632
|
-
|
|
633
|
-
let r = 0, g = 0, b = 0, a = 0;
|
|
634
|
-
|
|
635
|
-
for (let cy = 0; cy < side; cy++)
|
|
636
|
-
{
|
|
637
|
-
for (let cx = 0; cx < side; cx++)
|
|
638
|
-
{
|
|
639
|
-
let scy = sy + cy - halfSide;
|
|
640
|
-
let scx = sx + cx - halfSide;
|
|
641
|
-
|
|
642
|
-
if (scy >= 0 && scy < sh && scx >= 0 && scx < sw)
|
|
643
|
-
{
|
|
644
|
-
let srcOff = (scy * sw + scx) * 4;
|
|
645
|
-
let wt = weights[cy * side + cx];
|
|
646
|
-
r += srcData[srcOff] * wt;
|
|
647
|
-
g += srcData[srcOff + 1] * wt;
|
|
648
|
-
b += srcData[srcOff + 2] * wt;
|
|
649
|
-
a += srcData[srcOff + 3] * wt;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
dst[dstOff] = r;
|
|
655
|
-
dst[dstOff + 1] = g;
|
|
656
|
-
dst[dstOff + 2] = b;
|
|
657
|
-
dst[dstOff + 3] = a + alphaFac * (255 - a);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
return output;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
export function sharpen (data, adjust)
|
|
665
|
-
{
|
|
666
|
-
let adj = adjust ? adjust : 100;
|
|
667
|
-
adj /= 100;
|
|
668
|
-
|
|
669
|
-
if (adjust === 0) // reset value
|
|
670
|
-
adj = 0;
|
|
671
|
-
|
|
672
|
-
let weights = [
|
|
673
|
-
0, -adj, 0,
|
|
674
|
-
-adj, 4 * adj + 1, -adj,
|
|
675
|
-
0, -adj, 0
|
|
676
|
-
];
|
|
677
|
-
|
|
678
|
-
return addFilterToQueue(data, convolve, weights, 'Sharpness');
|
|
679
|
-
}
|