-
-
Notifications
You must be signed in to change notification settings - Fork 141
/
Copy pathgrabber_calibration.js
347 lines (289 loc) · 10.9 KB
/
grabber_calibration.js
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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
$(document).ready( function(){
if (window.matchMedia("(color-gamut: srgb)").matches) {
console.log(`Screen supports approximately the sRGB gamut or more.`);
}
if (window.matchMedia("(color-gamut: p3)").matches) {
console.log(`Screen supports approximately the gamut specified by the DCI P3 Color Space or more.`);
}
if (window.matchMedia("(color-gamut: rec2020)").matches) {
console.log(`Screen supports approximately the gamut specified by the ITU-R Recommendation BT.2020 Color Space or more.`);
}
let calibWiz = null;
let myInterval;
let currentTestBoard = 0;
let finish = false;
let running = false;
let saturation = 1;
let luminance = 1;
let gammaR = 1;
let gammaG = 1;
let gammaB = 1;
$("#select_classic_calibration_label").html($.i18n("option_calibration_classic"));
$("#select_video_calibration_label").html($.i18n("option_calibration_video"));
$("#video_calibration_overview").html($.i18n("video_calibration_overview"));
$("#btn_select_calibration").off('click').on('click', function() {
if($('#select_classic_calibration').is(':checked'))
{
$('#calibration_select_intro').hide();
$('#classic_calibration').show();
}
if($('#select_video_calibration').is(':checked'))
{
$('#calibration_select_intro').hide();
$('#video_calibration').show();
}
});
$("#btn_start_video_calibration").off('click').on('click', function() {
finish = false;
running = true;
startCalibrationWizard();
const calDebug = document.getElementById('chk_debug').checked;
const calLchCorrection = document.getElementById('chk_lchCorrection').checked;
requestLutCalibration("capture", calDebug, calLchCorrection);
});
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.addEventListener('click', function() {
if (!running)
{
if (canvas.classList.contains("fullscreen-canvas"))
canvas.classList.remove("fullscreen-canvas");
else
canvas.classList.add("fullscreen-canvas");
}
}, false);
performTranslation();
$("#grabber_calibration_intro").html($.i18n("grabber_calibration_expl"));
sendToHyperhdr("serverinfo", "", '"subscribe":["lut-calibration-update"]');
$(window.hyperhdr).off("cmd-lut-calibration-update").on("cmd-lut-calibration-update", function(event)
{
handleMessage(event);
});
$("#startCalibration").off('click').on('click', function() { startCalibration(); });
resetImage();
function resetImage()
{
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
var gradient = ctx.createConicGradient(0, canvas.width / 2, canvas.height / 2);
var s = 1/13;
gradient.addColorStop(s*0, `rgb(255, 0, 255)`);
gradient.addColorStop(s*1, `rgb(128, 0, 255)`);
gradient.addColorStop(s*2, `rgb(0, 0, 255)`);
gradient.addColorStop(s*3, `rgb(0, 128, 255)`);
gradient.addColorStop(s*5, `rgb(0, 255, 255)`);
gradient.addColorStop(s*6, `rgb(0, 255, 128)`);
gradient.addColorStop(s*7, `rgb(0, 255, 0)`);
gradient.addColorStop(s*8, `rgb(128, 255, 0)`);
gradient.addColorStop(s*9, `rgb(255, 255, 0)`);
gradient.addColorStop(s*10, `rgb(255, 128, 0)`);
gradient.addColorStop(s*11, `rgb(255, 0, 0)`);
gradient.addColorStop(s*12, `rgb(255, 0, 128)`);
gradient.addColorStop(s*13, `rgb(255, 0, 255)`);
// Set the fill style and draw a rectangle
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function startCalibrationWizard() {
$('#wiz_header').html('<svg data-src="svg/wizard.svg" fill="currentColor" class="svg4hyperhdr"></svg>' + $.i18n("main_menu_grabber_calibration_token"));
$('#wizp1_body').html('<h4 id="calibration_running_header" style="font-weight:bold;text-transform:uppercase;">' + $.i18n("perf_please_wait") + '</h4><div class="row pe-1 ps-2"><div class="col-12 p-3 mt-3 text-center"><svg data-src="svg/spinner_large.svg" fill="currentColor" class="svg4hyperhdr mb-2"></svg><br/></div></div>');
$('#wizp2_body').html('<h4 id="calibration_summary_header" style="font-weight:bold;text-transform:uppercase;"></h4><p id="calibration_summary"></p>');
$('#wizp1_footer').html('<button type="button" class="btn btn-danger" name="btn_wiz_abort"><svg data-src="svg/button_cancel.svg" fill="currentColor" class="svg4hyperhdr"></svg>' + $.i18n('general_btn_cancel') + '</button>');
$('#wizp2_footer').html('<button type="button" class="btn btn-success" name="btn_wiz_closeme_download"><svg data-src="svg/button_success.svg" fill="currentColor" class="svg4hyperhdr"></svg>' + $.i18n('general_btn_ok') + '</button>');
//open modal
calibWiz= new bootstrap.Modal($("#wizard_modal"), {
backdrop: "static",
keyboard: false
});
const backupCalibWizard = $("#wizard_modal").css("z-index");
$("#wizard_modal").css("z-index", "10000");
$('#wizp1').toggle(true);
$('#wizp2').toggle(false);
calibWiz.show();
$("[name='btn_wiz_abort']").off().on('click', function () {
$("#wizard_modal").css("z-index", backupCalibWizard);
requestLutCalibration("stop", false, false);
calibWiz.hide();
resetWizard(true);
reload();
});
$("[name='btn_wiz_closeme_download']").off().on('click', function () {
$("#wizard_modal").css("z-index", backupCalibWizard);
calibWiz.hide();
resetWizard(true);
reload();
});
}
function handleMessage(event)
{
let json = event.response.data;
if (!running)
return;
if (json.error != null)
{
clearInterval(myInterval);
document.body.style.overflow = 'visible';
canvas.classList.remove("fullscreen-canvas");
running = false;
resetImage();
if (calibWiz != null)
{
calibWiz.hide();
resetWizard(true);
}
alert("Error occured. Please consult the HyperHDR log.\n\n" + json.error);
return;
}
if (json.message != null)
{
if (json.start && calibWiz == null)
{
clearInterval(myInterval);
document.body.style.overflow = 'visible';
canvas.classList.remove("fullscreen-canvas");
resetImage();
startCalibrationWizard();
}
if (calibWiz != null)
{
let resElement = document.getElementById("calibration_running_header");
resElement.innerHTML = json.message;
}
}
if (json.finished != null)
{
clearInterval(myInterval);
finish = true;
canvas.classList.remove("fullscreen-canvas");
running = false;
document.body.style.overflow = 'visible';
resetImage();
let resElement = document.getElementById("calibration_summary_header");
resElement.innerHTML = `Finished!<br/>If the new LUT file was successfully created then you can find the path in the HyperHDR logs.<br/>Usually it's 'lut_lin_tables.3d' in your home HyperHDR folder.`;
$('#wizp1').toggle(false);
$('#wizp2').toggle(true);
return;
}
}
function startCalibration()
{
if (matchMedia('(display-mode: fullscreen)').matches)
{
document.body.style.overflow = 'hidden';
canvas.classList.add("fullscreen-canvas");
finish = false;
running = true;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawImage();
setTimeout(() => {
const calDebug = document.getElementById('chk_debug2').checked;
const calLchCorrection = document.getElementById('chk_lchCorrection2').checked;
requestLutCalibration("capture", calDebug, calLchCorrection);
}, 100);
}
else
alert('Please run fullscreen mode (F11)');
};
const SCREEN_BLOCKS_X = 48;
const SCREEN_BLOCKS_Y = 30;
const SCREEN_COLOR_STEP = 16;
const SCREEN_COLOR_DIMENSION = Math.floor(256 / SCREEN_COLOR_STEP) + 1;
const SCREEN_YUV_RANGE_LIMIT = 2;
const SCREEN_CRC_LINES = 2;
const SCREEN_CRC_COUNT = 5;
const SCREEN_MAX_CRC_BRIGHTNESS_ERROR = 1;
const SCREEN_MAX_COLOR_NOISE_ERROR = 8;
const SCREEN_SAMPLES_PER_BOARD = Math.floor(SCREEN_BLOCKS_X / 2) * (SCREEN_BLOCKS_Y - SCREEN_CRC_LINES);
const SCREEN_LAST_BOARD_INDEX = Math.floor(Math.pow(SCREEN_COLOR_DIMENSION, 3) / SCREEN_SAMPLES_PER_BOARD);
class int2 {
constructor(_x, _y) {
this.x = _x;
this.y = _y;
}
}
class byte3 {
constructor(_x, _y, _z) {
this.x = _x;
this.y = _y;
this.z = _z;
}
}
function indexToColorAndPos(index, color, position)
{
let currentIndex = index % SCREEN_SAMPLES_PER_BOARD;
let boardIndex = Math.floor(index / SCREEN_SAMPLES_PER_BOARD);
position.y = 1 + Math.floor(currentIndex / Math.floor(SCREEN_BLOCKS_X / 2));
position.x = (currentIndex % Math.floor(SCREEN_BLOCKS_X / 2)) * 2 + ((position.y + boardIndex )% 2);
const B = (index % SCREEN_COLOR_DIMENSION) * SCREEN_COLOR_STEP;
const G = (Math.floor(index / (SCREEN_COLOR_DIMENSION)) % SCREEN_COLOR_DIMENSION) * SCREEN_COLOR_STEP;
const R = Math.floor(index / (SCREEN_COLOR_DIMENSION * SCREEN_COLOR_DIMENSION)) * SCREEN_COLOR_STEP;
color.x = Math.min(R, 255);
color.y = Math.min(G, 255);
color.z = Math.min(B, 255);
return boardIndex;
}
function saveImage(delta, boardIndex, margin)
{
for (let line = 0; line < SCREEN_BLOCKS_Y; line += SCREEN_BLOCKS_Y - 1)
{
let position = new int2 ((line + boardIndex) % 2, line);
for (let x = 0; x < boardIndex + SCREEN_CRC_COUNT; x++, position.x += 2)
{
const start = new int2 (position.x * delta.x, position.y * delta.y);
const end = new int2 ( ((position.x + 1) * delta.x) - 1, ((position.y + 1) * delta.y) - 1);
fastBox(start.x + margin.x, start.y + margin.y, end.x - margin.x, end.y - margin.y, 255, 255, 255);
}
}
};
function createTestBoards(boardIndex)
{
const margin = new int2(3, 2);
let maxIndex = Math.pow(SCREEN_COLOR_DIMENSION, 3);
const image = new int2(canvas.width, canvas.height);
const delta = new int2(image.x / SCREEN_BLOCKS_X, image.y / SCREEN_BLOCKS_Y);
ctx.fillStyle = 'black';
ctx.fillRect(0,0, image.x, image.y);
let lastBoard = 0;
for (let index = 0; index < maxIndex; index++)
{
let color = new byte3(0,0,0);
let position = new int2(0,0);
let currentBoard = indexToColorAndPos(index, color, position);
if (currentBoard < 0)
return;
if (boardIndex + 1 == currentBoard)
{
saveImage(delta, boardIndex, margin);
return;
}
else if (boardIndex > currentBoard)
continue;
if (lastBoard != currentBoard)
{
ctx.fillStyle = 'black';
ctx.fillRect(0,0, image.x, image.y);
}
lastBoard = currentBoard;
const start = new int2 ( position.x * delta.x, position.y * delta.y);
const end = new int2 ( ((position.x + 1) * delta.x) - 1, ((position.y + 1) * delta.y) - 1);
fastBox(start.x + margin.x, start.y + margin.y, end.x - margin.x, end.y - margin.y, color.x, color.y, color.z);
}
saveImage(delta, boardIndex, margin);
}
function fastBox(x1, y1, x2, y2, c1, c2 ,c3)
{
ctx.fillStyle = `rgb(${c1}, ${c2}, ${c3})`;
ctx.fillRect(x1, y1, (x2 - x1), (y2 - y1));
}
function drawImage()
{
clearInterval(myInterval);
myInterval= setInterval( function(){
currentTestBoard = (currentTestBoard + 1) % (SCREEN_LAST_BOARD_INDEX + 1);
createTestBoards(currentTestBoard);
}, 3000);
currentTestBoard = 0;
createTestBoards(currentTestBoard);
}
});