soiz1 commited on
Commit
933fc37
·
verified ·
1 Parent(s): 663c994

Update script.js

Browse files
Files changed (1) hide show
  1. script.js +72 -115
script.js CHANGED
@@ -7,9 +7,6 @@ document.addEventListener('DOMContentLoaded', function() {
7
  const saturationSlider = document.getElementById('saturation');
8
  const shadowsSlider = document.getElementById('shadows');
9
  const highlightsSlider = document.getElementById('highlights');
10
- const hueRedSlider = document.getElementById('hue-red');
11
- const hueGreenSlider = document.getElementById('hue-green');
12
- const hueBlueSlider = document.getElementById('hue-blue');
13
  const brightnessValue = document.getElementById('brightness-value');
14
  const contrastValue = document.getElementById('contrast-value');
15
  const saturationValue = document.getElementById('saturation-value');
@@ -20,19 +17,20 @@ document.addEventListener('DOMContentLoaded', function() {
20
  const downloadBtn = document.getElementById('download-btn');
21
  const loadingOverlay = document.getElementById('loading-overlay');
22
 
23
- // RGBカーブ用のキャンバス
24
  const redCurveCanvas = document.getElementById('red-curve');
25
  const greenCurveCanvas = document.getElementById('green-curve');
26
  const blueCurveCanvas = document.getElementById('blue-curve');
 
27
 
28
  // カーブ制御用の変数
29
  let redCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
30
  let greenCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
31
  let blueCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
 
32
 
33
  let camanInstance = null;
34
  let originalImageData = null;
35
- let currentFilters = {};
36
 
37
  // 画像アップロードの処理
38
  imageUpload.addEventListener('change', function(e) {
@@ -71,7 +69,7 @@ document.addEventListener('DOMContentLoaded', function() {
71
  camanInstance = this;
72
  originalImageData = this.canvas.toDataURL();
73
 
74
- // RGBカーブを初期化
75
  initCurves();
76
  hideLoading();
77
  });
@@ -109,69 +107,22 @@ document.addEventListener('DOMContentLoaded', function() {
109
  }, 100);
110
  });
111
 
112
- // フィルターを適用する関数(強化版)
113
  function applyFilters() {
114
  if (!camanInstance) return;
115
 
116
  camanInstance.revert(false);
117
 
118
- // 現在のフィルター設定を保存
119
- currentFilters = {
120
- brightness: parseInt(brightnessSlider.value),
121
- contrast: parseInt(contrastSlider.value),
122
- saturation: parseInt(saturationSlider.value),
123
- shadows: parseInt(shadowsSlider.value),
124
- highlights: parseInt(highlightsSlider.value),
125
- hueRed: parseInt(hueRedSlider.value),
126
- hueGreen: parseInt(hueGreenSlider.value),
127
- hueBlue: parseInt(hueBlueSlider.value)
128
- };
129
-
130
- // 明るさ(範囲拡大: -100 to 100 → -150 to 150)
131
- camanInstance.brightness(currentFilters.brightness * 1.5);
132
-
133
- // コントラスト(効果を強化)
134
- camanInstance.contrast(currentFilters.contrast * 1.5);
135
-
136
- // 彩度
137
- camanInstance.saturation(currentFilters.saturation);
138
-
139
- // シャドウ(効果を強化、範囲拡大)
140
- if (currentFilters.shadows > 0) {
141
- camanInstance.shadows(currentFilters.shadows * 2);
142
- } else {
143
- camanInstance.exposure(currentFilters.shadows / 5);
144
- }
145
-
146
- // ハイライト(効果を強化、範囲拡大)
147
- if (currentFilters.highlights > 0) {
148
- camanInstance.highlights(currentFilters.highlights * 2);
149
- } else {
150
- camanInstance.exposure(currentFilters.highlights / 5);
151
- }
152
-
153
- // HSL調整
154
- camanInstance.hue(currentFilters.hueRed / 2);
155
- camanInstance.hue(currentFilters.hueGreen / 2);
156
- camanInstance.hue(currentFilters.hueBlue / 2);
157
 
158
  // RGBカーブを適用
159
  applyRgbCurves();
160
 
161
- // 追加フィルター: シャープネス
162
- if (currentFilters.sharpness) {
163
- camanInstance.sharpen(currentFilters.sharpness);
164
- }
165
-
166
- // 追加フィルター: ノイズ
167
- if (currentFilters.noise) {
168
- camanInstance.noise(currentFilters.noise);
169
- }
170
-
171
- // 追加フィルター: ビネット
172
- if (currentFilters.vignette) {
173
- camanInstance.vignette("10%", currentFilters.vignette * 2);
174
- }
175
 
176
  camanInstance.render();
177
  }
@@ -181,10 +132,12 @@ document.addEventListener('DOMContentLoaded', function() {
181
  drawCurve(redCurveCanvas, redCurvePoints, 'red');
182
  drawCurve(greenCurveCanvas, greenCurvePoints, 'green');
183
  drawCurve(blueCurveCanvas, blueCurvePoints, 'blue');
 
184
 
185
  setupCurveInteraction(redCurveCanvas, redCurvePoints, 'red');
186
  setupCurveInteraction(greenCurveCanvas, greenCurvePoints, 'green');
187
  setupCurveInteraction(blueCurveCanvas, blueCurvePoints, 'blue');
 
188
  }
189
 
190
  // カーブを描画
@@ -285,6 +238,9 @@ document.addEventListener('DOMContentLoaded', function() {
285
  }
286
 
287
  drawCurve(canvas, points, color);
 
 
 
288
  });
289
 
290
  canvas.addEventListener('mousemove', function(e) {
@@ -309,16 +265,25 @@ document.addEventListener('DOMContentLoaded', function() {
309
  draggedPoint.y = y;
310
 
311
  drawCurve(canvas, points, color);
 
 
 
312
  });
313
 
314
  canvas.addEventListener('mouseup', function() {
315
  isDragging = false;
316
  draggedPoint = null;
 
 
 
317
  });
318
 
319
  canvas.addEventListener('mouseleave', function() {
320
  isDragging = false;
321
  draggedPoint = null;
 
 
 
322
  });
323
 
324
  // ポイントを削除するダブルクリック
@@ -336,6 +301,9 @@ document.addEventListener('DOMContentLoaded', function() {
336
  if (distance < 15) {
337
  points.splice(i, 1);
338
  drawCurve(canvas, points, color);
 
 
 
339
  return;
340
  }
341
  }
@@ -360,6 +328,48 @@ document.addEventListener('DOMContentLoaded', function() {
360
  });
361
  }
362
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  // カーブデータを作成
364
  function createCurveData(points) {
365
  points.sort((a, b) => a.x - b.x);
@@ -396,9 +406,6 @@ document.addEventListener('DOMContentLoaded', function() {
396
  saturationSlider.value = 0;
397
  shadowsSlider.value = 0;
398
  highlightsSlider.value = 0;
399
- hueRedSlider.value = 0;
400
- hueGreenSlider.value = 0;
401
- hueBlueSlider.value = 0;
402
 
403
  brightnessValue.textContent = '0';
404
  contrastValue.textContent = '0';
@@ -410,10 +417,12 @@ document.addEventListener('DOMContentLoaded', function() {
410
  redCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
411
  greenCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
412
  blueCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
 
413
 
414
  drawCurve(redCurveCanvas, redCurvePoints, 'red');
415
  drawCurve(greenCurveCanvas, greenCurvePoints, 'green');
416
  drawCurve(blueCurveCanvas, blueCurvePoints, 'blue');
 
417
 
418
  // 画像をリセット
419
  const img = new Image();
@@ -429,9 +438,6 @@ document.addEventListener('DOMContentLoaded', function() {
429
  });
430
  };
431
  img.src = originalImageData;
432
-
433
- // フィルター設定をリセット
434
- currentFilters = {};
435
  });
436
 
437
  // ダウンロードボタン
@@ -452,53 +458,4 @@ document.addEventListener('DOMContentLoaded', function() {
452
  function hideLoading() {
453
  loadingOverlay.style.display = 'none';
454
  }
455
-
456
- // 追加機能: キーボードショートカット
457
- document.addEventListener('keydown', function(e) {
458
- if (e.ctrlKey && e.key === 'z') {
459
- resetBtn.click();
460
- } else if (e.ctrlKey && e.key === 's') {
461
- downloadBtn.click();
462
- e.preventDefault();
463
- } else if (e.key === 'Enter') {
464
- applyBtn.click();
465
- }
466
- });
467
-
468
- // 追加機能: プリセットフィルター
469
- function applyPreset(presetName) {
470
- switch(presetName) {
471
- case 'vintage':
472
- brightnessSlider.value = 10;
473
- contrastSlider.value = 20;
474
- saturationSlider.value = -30;
475
- shadowsSlider.value = 15;
476
- highlightsSlider.value = -10;
477
- hueRedSlider.value = 10;
478
- break;
479
- case 'dramatic':
480
- brightnessSlider.value = -10;
481
- contrastSlider.value = 50;
482
- saturationSlider.value = -20;
483
- shadowsSlider.value = 30;
484
- highlightsSlider.value = -20;
485
- break;
486
- case 'bright':
487
- brightnessSlider.value = 30;
488
- contrastSlider.value = 20;
489
- saturationSlider.value = 40;
490
- shadowsSlider.value = 20;
491
- highlightsSlider.value = 10;
492
- break;
493
- }
494
-
495
- // スライダー値を更新
496
- brightnessValue.textContent = brightnessSlider.value;
497
- contrastValue.textContent = contrastSlider.value;
498
- saturationValue.textContent = saturationSlider.value;
499
- shadowsValue.textContent = shadowsSlider.value;
500
- highlightsValue.textContent = highlightsSlider.value;
501
-
502
- applyBtn.click();
503
- }
504
  });
 
7
  const saturationSlider = document.getElementById('saturation');
8
  const shadowsSlider = document.getElementById('shadows');
9
  const highlightsSlider = document.getElementById('highlights');
 
 
 
10
  const brightnessValue = document.getElementById('brightness-value');
11
  const contrastValue = document.getElementById('contrast-value');
12
  const saturationValue = document.getElementById('saturation-value');
 
17
  const downloadBtn = document.getElementById('download-btn');
18
  const loadingOverlay = document.getElementById('loading-overlay');
19
 
20
+ // カーブ用のキャンバス
21
  const redCurveCanvas = document.getElementById('red-curve');
22
  const greenCurveCanvas = document.getElementById('green-curve');
23
  const blueCurveCanvas = document.getElementById('blue-curve');
24
+ const luminanceCurveCanvas = document.getElementById('luminance-curve');
25
 
26
  // カーブ制御用の変数
27
  let redCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
28
  let greenCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
29
  let blueCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
30
+ let luminanceCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
31
 
32
  let camanInstance = null;
33
  let originalImageData = null;
 
34
 
35
  // 画像アップロードの処理
36
  imageUpload.addEventListener('change', function(e) {
 
69
  camanInstance = this;
70
  originalImageData = this.canvas.toDataURL();
71
 
72
+ // カーブを初期化
73
  initCurves();
74
  hideLoading();
75
  });
 
107
  }, 100);
108
  });
109
 
110
+ // フィルターを適用する関数
111
  function applyFilters() {
112
  if (!camanInstance) return;
113
 
114
  camanInstance.revert(false);
115
 
116
+ // 基本調整
117
+ camanInstance.brightness(parseInt(brightnessSlider.value));
118
+ camanInstance.contrast(parseInt(contrastSlider.value) * 1.5); // コントラスト強化
119
+ camanInstance.saturation(parseInt(saturationSlider.value));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  // RGBカーブを適用
122
  applyRgbCurves();
123
 
124
+ // 輝度カーブを適用(シャドウ/ハイライト調整)
125
+ applyLuminanceCurve();
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
  camanInstance.render();
128
  }
 
132
  drawCurve(redCurveCanvas, redCurvePoints, 'red');
133
  drawCurve(greenCurveCanvas, greenCurvePoints, 'green');
134
  drawCurve(blueCurveCanvas, blueCurvePoints, 'blue');
135
+ drawCurve(luminanceCurveCanvas, luminanceCurvePoints, '#888');
136
 
137
  setupCurveInteraction(redCurveCanvas, redCurvePoints, 'red');
138
  setupCurveInteraction(greenCurveCanvas, greenCurvePoints, 'green');
139
  setupCurveInteraction(blueCurveCanvas, blueCurvePoints, 'blue');
140
+ setupCurveInteraction(luminanceCurveCanvas, luminanceCurvePoints, '#888');
141
  }
142
 
143
  // カーブを描画
 
238
  }
239
 
240
  drawCurve(canvas, points, color);
241
+ if (canvas !== luminanceCurveCanvas) {
242
+ applyBtn.click();
243
+ }
244
  });
245
 
246
  canvas.addEventListener('mousemove', function(e) {
 
265
  draggedPoint.y = y;
266
 
267
  drawCurve(canvas, points, color);
268
+ if (canvas !== luminanceCurveCanvas) {
269
+ applyBtn.click();
270
+ }
271
  });
272
 
273
  canvas.addEventListener('mouseup', function() {
274
  isDragging = false;
275
  draggedPoint = null;
276
+ if (canvas === luminanceCurveCanvas) {
277
+ applyBtn.click();
278
+ }
279
  });
280
 
281
  canvas.addEventListener('mouseleave', function() {
282
  isDragging = false;
283
  draggedPoint = null;
284
+ if (canvas === luminanceCurveCanvas && isDragging) {
285
+ applyBtn.click();
286
+ }
287
  });
288
 
289
  // ポイントを削除するダブルクリック
 
301
  if (distance < 15) {
302
  points.splice(i, 1);
303
  drawCurve(canvas, points, color);
304
+ if (canvas !== luminanceCurveCanvas) {
305
+ applyBtn.click();
306
+ }
307
  return;
308
  }
309
  }
 
328
  });
329
  }
330
 
331
+ // 輝度カーブを適用(連続的なシャドウ/ハイライト調整)
332
+ function applyLuminanceCurve() {
333
+ if (!camanInstance) return;
334
+
335
+ const luminanceCurve = createCurveData(luminanceCurvePoints);
336
+ const shadowAmount = parseInt(shadowsSlider.value) / 100 * 50; // -50から50の範囲に調整
337
+ const highlightAmount = parseInt(highlightsSlider.value) / 100 * 50;
338
+
339
+ camanInstance.process("luminanceAdjustment", function(rgba) {
340
+ // ピクセルの輝度を計算
341
+ const luminance = 0.299 * rgba.r + 0.587 * rgba.g + 0.114 * rgba.b;
342
+
343
+ // 輝度カーブから調整値を取得
344
+ const curveAdjustment = (luminanceCurve[luminance] - luminance) / 255 * 100;
345
+
346
+ // シャドウ/ハイライト調整を適用
347
+ let adjustment = 0;
348
+
349
+ // シャドウ調整(低輝度ほど強く適用)
350
+ if (shadowAmount !== 0) {
351
+ const shadowFactor = 1 - (luminance / 255); // 0(明るい)~1(暗い)
352
+ adjustment += shadowAmount * shadowFactor;
353
+ }
354
+
355
+ // ハイライト調整(高輝度ほど強く適用)
356
+ if (highlightAmount !== 0) {
357
+ const highlightFactor = luminance / 255; // 0(暗い)~1(明るい)
358
+ adjustment += highlightAmount * highlightFactor;
359
+ }
360
+
361
+ // 輝度カーブの調整を追加
362
+ adjustment += curveAdjustment;
363
+
364
+ // 調整を適用
365
+ rgba.r = Math.min(255, Math.max(0, rgba.r + adjustment));
366
+ rgba.g = Math.min(255, Math.max(0, rgba.g + adjustment));
367
+ rgba.b = Math.min(255, Math.max(0, rgba.b + adjustment));
368
+
369
+ return rgba;
370
+ });
371
+ }
372
+
373
  // カーブデータを作成
374
  function createCurveData(points) {
375
  points.sort((a, b) => a.x - b.x);
 
406
  saturationSlider.value = 0;
407
  shadowsSlider.value = 0;
408
  highlightsSlider.value = 0;
 
 
 
409
 
410
  brightnessValue.textContent = '0';
411
  contrastValue.textContent = '0';
 
417
  redCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
418
  greenCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
419
  blueCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
420
+ luminanceCurvePoints = [{x: 0, y: 0}, {x: 255, y: 255}];
421
 
422
  drawCurve(redCurveCanvas, redCurvePoints, 'red');
423
  drawCurve(greenCurveCanvas, greenCurvePoints, 'green');
424
  drawCurve(blueCurveCanvas, blueCurvePoints, 'blue');
425
+ drawCurve(luminanceCurveCanvas, luminanceCurvePoints, '#888');
426
 
427
  // 画像をリセット
428
  const img = new Image();
 
438
  });
439
  };
440
  img.src = originalImageData;
 
 
 
441
  });
442
 
443
  // ダウンロードボタン
 
458
  function hideLoading() {
459
  loadingOverlay.style.display = 'none';
460
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  });