SenY commited on
Commit
79a900a
·
1 Parent(s): 8f9ad04

postprocess

Browse files
Files changed (1) hide show
  1. postprocess/hue.js +136 -0
postprocess/hue.js ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { BasePostProcess } from './base.js';
2
+
3
+ /**
4
+ * 色相を変更するポストプロセス
5
+ */
6
+ export class HuePostProcess extends BasePostProcess {
7
+ constructor() {
8
+ super();
9
+ this.name = 'hue';
10
+ this.label = '色相';
11
+ this.ui = {
12
+ template: `
13
+ <div class="mb-2">
14
+ <label class="form-label">色相の変更</label>
15
+ <input type="range" class="form-range" min="0" max="359" value="0" id="hueRotate">
16
+ <div class="range-value"><span id="hueRotateValue">0</span>°</div>
17
+ </div>
18
+ `
19
+ };
20
+ }
21
+
22
+ /**
23
+ * RGBからHSLに変換
24
+ * @private
25
+ */
26
+ rgbToHsl(r, g, b) {
27
+ r /= 255;
28
+ g /= 255;
29
+ b /= 255;
30
+ const max = Math.max(r, g, b);
31
+ const min = Math.min(r, g, b);
32
+ let h, s, l = (max + min) / 2;
33
+
34
+ if (max === min) {
35
+ h = s = 0;
36
+ } else {
37
+ const d = max - min;
38
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
39
+ switch (max) {
40
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
41
+ case g: h = (b - r) / d + 2; break;
42
+ case b: h = (r - g) / d + 4; break;
43
+ }
44
+ h /= 6;
45
+ }
46
+
47
+ return [h * 360, s * 100, l * 100];
48
+ }
49
+
50
+ /**
51
+ * HSLからRGBに変換
52
+ * @private
53
+ */
54
+ hslToRgb(h, s, l) {
55
+ h /= 360;
56
+ s /= 100;
57
+ l /= 100;
58
+ let r, g, b;
59
+
60
+ if (s === 0) {
61
+ r = g = b = l;
62
+ } else {
63
+ const hue2rgb = (p, q, t) => {
64
+ if (t < 0) t += 1;
65
+ if (t > 1) t -= 1;
66
+ if (t < 1/6) return p + (q - p) * 6 * t;
67
+ if (t < 1/2) return q;
68
+ if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
69
+ return p;
70
+ };
71
+
72
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
73
+ const p = 2 * l - q;
74
+ r = hue2rgb(p, q, h + 1/3);
75
+ g = hue2rgb(p, q, h);
76
+ b = hue2rgb(p, q, h - 1/3);
77
+ }
78
+
79
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
80
+ }
81
+
82
+ /**
83
+ * 色相を変更する処理を適用
84
+ * @param {HTMLCanvasElement} canvas - 処理対象のcanvas
85
+ * @returns {HTMLCanvasElement} - 処理後のcanvas
86
+ */
87
+ async apply(canvas) {
88
+ // 色相の値を取得
89
+ const hueRotate = parseInt(document.getElementById('hueRotate').value);
90
+ if (hueRotate === 0) return canvas;
91
+
92
+ // 新しいcanvasを作成
93
+ const newCanvas = document.createElement('canvas');
94
+ newCanvas.width = canvas.width;
95
+ newCanvas.height = canvas.height;
96
+ const ctx = newCanvas.getContext('2d');
97
+
98
+ // 元のcanvasを描画
99
+ ctx.drawImage(canvas, 0, 0);
100
+
101
+ // ピクセルデータを取得
102
+ const imageData = ctx.getImageData(0, 0, newCanvas.width, newCanvas.height);
103
+ const data = imageData.data;
104
+
105
+ // 各ピクセルの色相を変更
106
+ for (let i = 0; i < data.length; i += 4) {
107
+ const r = data[i];
108
+ const g = data[i + 1];
109
+ const b = data[i + 2];
110
+ const a = data[i + 3];
111
+
112
+ // アルファ値が0の場合はスキップ
113
+ if (a === 0) continue;
114
+
115
+ // RGBからHSLに変換
116
+ let [h, s, l] = this.rgbToHsl(r, g, b);
117
+
118
+ // 色相を回転
119
+ h = (h + hueRotate) % 360;
120
+ if (h < 0) h += 360;
121
+
122
+ // HSLからRGBに変換
123
+ const [newR, newG, newB] = this.hslToRgb(h, s, l);
124
+
125
+ // 新しい色を設定
126
+ data[i] = newR;
127
+ data[i + 1] = newG;
128
+ data[i + 2] = newB;
129
+ }
130
+
131
+ // 変更した画像データを描画
132
+ ctx.putImageData(imageData, 0, 0);
133
+
134
+ return newCanvas;
135
+ }
136
+ }