image-color-grading 1.0.0 → 1.0.2

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/package.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
2
  "name": "image-color-grading",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "基于 WebGL 的高性能图像调色库,支持亮度、对比度、饱和度、色温等 22+ 种调色参数",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
6
+ "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "import": "./dist/index.js",
12
- "types": "./dist/index.d.ts"
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
13
19
  }
14
20
  },
15
21
  "files": [
@@ -17,8 +23,8 @@
17
23
  "README.md"
18
24
  ],
19
25
  "scripts": {
20
- "build": "tsc",
21
- "dev": "tsc --watch",
26
+ "build": "tsup",
27
+ "dev": "tsup --watch",
22
28
  "prepublishOnly": "npm run build"
23
29
  },
24
30
  "keywords": [
@@ -42,6 +48,8 @@
42
48
  "url": ""
43
49
  },
44
50
  "devDependencies": {
51
+ "terser": "^5.0.0",
52
+ "tsup": "^8.0.0",
45
53
  "typescript": "^5.0.0"
46
54
  },
47
55
  "engines": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EACV,oBAAoB,EACpB,2BAA2B,EAC3B,aAAa,GACd,MAAM,SAAS,CAAC"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -1,109 +0,0 @@
1
- import type { ColorGradingSettings, PartialColorGradingSettings, ExportOptions } from './types';
2
- /**
3
- * 默认设置
4
- */
5
- export declare const defaultSettings: ColorGradingSettings;
6
- /**
7
- * 图像调色处理器
8
- *
9
- * @example
10
- * ```ts
11
- * const processor = new ImageColorGrading();
12
- * await processor.loadImage('path/to/image.jpg');
13
- * processor.setSettings({ brightness: 20, contrast: 10 });
14
- * processor.render();
15
- * const dataUrl = processor.toDataURL();
16
- * ```
17
- */
18
- export declare class ImageColorGrading {
19
- private canvas;
20
- private resources;
21
- private settings;
22
- private imageLoaded;
23
- /**
24
- * 创建图像调色处理器
25
- * @param canvas - 可选的 canvas 元素,不传则自动创建
26
- */
27
- constructor(canvas?: HTMLCanvasElement);
28
- /**
29
- * 获取 canvas 元素
30
- */
31
- getCanvas(): HTMLCanvasElement;
32
- /**
33
- * 获取当前设置
34
- */
35
- getSettings(): ColorGradingSettings;
36
- /**
37
- * 设置调色参数
38
- * @param newSettings - 部分或全部设置参数
39
- */
40
- setSettings(newSettings: PartialColorGradingSettings): void;
41
- /**
42
- * 重置所有设置为默认值
43
- */
44
- resetSettings(): void;
45
- /**
46
- * 从 URL 加载图像
47
- * @param url - 图像 URL
48
- * @returns Promise
49
- */
50
- loadImage(url: string): Promise<void>;
51
- /**
52
- * 从 HTMLImageElement 加载图像
53
- * @param image - 图像元素
54
- */
55
- loadFromImage(image: HTMLImageElement): void;
56
- /**
57
- * 从 File 对象加载图像
58
- * @param file - File 对象
59
- * @returns Promise
60
- */
61
- loadFromFile(file: File): Promise<void>;
62
- /**
63
- * 从 ImageData 加载图像
64
- * @param imageData - ImageData 对象
65
- */
66
- loadFromImageData(imageData: ImageData): void;
67
- /**
68
- * 渲染图像
69
- */
70
- render(): void;
71
- /**
72
- * 导出为 Data URL
73
- * @param options - 导出选项
74
- * @returns Data URL 字符串
75
- */
76
- toDataURL(options?: ExportOptions): string;
77
- /**
78
- * 导出为 Blob
79
- * @param options - 导出选项
80
- * @returns Promise<Blob>
81
- */
82
- toBlob(options?: ExportOptions): Promise<Blob>;
83
- /**
84
- * 获取 ImageData
85
- * @returns ImageData
86
- */
87
- getImageData(): ImageData;
88
- /**
89
- * 获取图像尺寸
90
- */
91
- getSize(): {
92
- width: number;
93
- height: number;
94
- };
95
- /**
96
- * 检查是否已加载图像
97
- */
98
- isLoaded(): boolean;
99
- /**
100
- * 销毁资源
101
- */
102
- dispose(): void;
103
- private getWebGLContext;
104
- private initFromImage;
105
- private initResources;
106
- private disposeResources;
107
- private drawFrame;
108
- }
109
- //# sourceMappingURL=processor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processor.d.ts","sourceRoot":"","sources":["../src/processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,2BAA2B,EAI3B,aAAa,EACd,MAAM,SAAS,CAAC;AAYjB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,oBAsB7B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAAgD;IAChE,OAAO,CAAC,WAAW,CAAS;IAE5B;;;OAGG;gBACS,MAAM,CAAC,EAAE,iBAAiB;IAItC;;OAEG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;OAEG;IACH,WAAW,IAAI,oBAAoB;IAInC;;;OAGG;IACH,WAAW,CAAC,WAAW,EAAE,2BAA2B,GAAG,IAAI;IAO3D;;OAEG;IACH,aAAa,IAAI,IAAI;IAOrB;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAerC;;;OAGG;IACH,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAI5C;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAevC;;;OAGG;IACH,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAoC7C;;OAEG;IACH,MAAM,IAAI,IAAI;IAQd;;;;OAIG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM;IAM1C;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9C;;;OAGG;IACH,YAAY,IAAI,SAAS;IAiBzB;;OAEG;IACH,OAAO,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAO5C;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,aAAa;IA4ErB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,SAAS;CAuUlB"}
package/dist/processor.js DELETED
@@ -1,527 +0,0 @@
1
- import * as shaders from './shaders';
2
- import { buildProgram, createRenderTarget, createPaletteTexture, updatePaletteTexture, buildBlackPalette, buildContrastMatrix, buildSaturationMatrix, } from './utils';
3
- /**
4
- * 默认设置
5
- */
6
- export const defaultSettings = {
7
- vibrance: 0,
8
- saturation: 0,
9
- temperature: 0,
10
- tint: 0,
11
- hue: 0,
12
- brightness: 0,
13
- exposure: 0,
14
- contrast: 0,
15
- blacks: 0,
16
- whites: 0,
17
- highlights: 0,
18
- shadows: 0,
19
- dehaze: 0,
20
- bloom: 0,
21
- glamour: 0,
22
- clarity: 0,
23
- sharpen: 0,
24
- smooth: 0,
25
- blur: 0,
26
- vignette: 0,
27
- grain: 0,
28
- };
29
- /**
30
- * 图像调色处理器
31
- *
32
- * @example
33
- * ```ts
34
- * const processor = new ImageColorGrading();
35
- * await processor.loadImage('path/to/image.jpg');
36
- * processor.setSettings({ brightness: 20, contrast: 10 });
37
- * processor.render();
38
- * const dataUrl = processor.toDataURL();
39
- * ```
40
- */
41
- export class ImageColorGrading {
42
- /**
43
- * 创建图像调色处理器
44
- * @param canvas - 可选的 canvas 元素,不传则自动创建
45
- */
46
- constructor(canvas) {
47
- this.resources = null;
48
- this.settings = { ...defaultSettings };
49
- this.imageLoaded = false;
50
- this.canvas = canvas || document.createElement('canvas');
51
- }
52
- /**
53
- * 获取 canvas 元素
54
- */
55
- getCanvas() {
56
- return this.canvas;
57
- }
58
- /**
59
- * 获取当前设置
60
- */
61
- getSettings() {
62
- return { ...this.settings };
63
- }
64
- /**
65
- * 设置调色参数
66
- * @param newSettings - 部分或全部设置参数
67
- */
68
- setSettings(newSettings) {
69
- this.settings = { ...this.settings, ...newSettings };
70
- if (this.resources) {
71
- this.render();
72
- }
73
- }
74
- /**
75
- * 重置所有设置为默认值
76
- */
77
- resetSettings() {
78
- this.settings = { ...defaultSettings };
79
- if (this.resources) {
80
- this.render();
81
- }
82
- }
83
- /**
84
- * 从 URL 加载图像
85
- * @param url - 图像 URL
86
- * @returns Promise
87
- */
88
- loadImage(url) {
89
- return new Promise((resolve, reject) => {
90
- const image = new Image();
91
- image.crossOrigin = 'anonymous';
92
- image.onload = () => {
93
- this.initFromImage(image);
94
- resolve();
95
- };
96
- image.onerror = () => {
97
- reject(new Error(`Failed to load image: ${url}`));
98
- };
99
- image.src = url;
100
- });
101
- }
102
- /**
103
- * 从 HTMLImageElement 加载图像
104
- * @param image - 图像元素
105
- */
106
- loadFromImage(image) {
107
- this.initFromImage(image);
108
- }
109
- /**
110
- * 从 File 对象加载图像
111
- * @param file - File 对象
112
- * @returns Promise
113
- */
114
- loadFromFile(file) {
115
- return new Promise((resolve, reject) => {
116
- const url = URL.createObjectURL(file);
117
- this.loadImage(url)
118
- .then(() => {
119
- URL.revokeObjectURL(url);
120
- resolve();
121
- })
122
- .catch((err) => {
123
- URL.revokeObjectURL(url);
124
- reject(err);
125
- });
126
- });
127
- }
128
- /**
129
- * 从 ImageData 加载图像
130
- * @param imageData - ImageData 对象
131
- */
132
- loadFromImageData(imageData) {
133
- const { width, height, data } = imageData;
134
- this.canvas.width = width;
135
- this.canvas.height = height;
136
- const gl = this.getWebGLContext();
137
- if (!gl)
138
- throw new Error('WebGL not supported');
139
- this.disposeResources();
140
- gl.viewport(0, 0, width, height);
141
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
142
- const sourceTexture = gl.createTexture();
143
- if (!sourceTexture)
144
- throw new Error('Failed to create texture');
145
- gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
146
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
147
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
148
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
149
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
150
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
151
- this.initResources(gl, width, height, sourceTexture);
152
- }
153
- /**
154
- * 渲染图像
155
- */
156
- render() {
157
- if (!this.resources) {
158
- console.warn('No image loaded');
159
- return;
160
- }
161
- this.drawFrame(this.resources, this.settings);
162
- }
163
- /**
164
- * 导出为 Data URL
165
- * @param options - 导出选项
166
- * @returns Data URL 字符串
167
- */
168
- toDataURL(options) {
169
- const format = options?.format || 'image/png';
170
- const quality = options?.quality;
171
- return this.canvas.toDataURL(format, quality);
172
- }
173
- /**
174
- * 导出为 Blob
175
- * @param options - 导出选项
176
- * @returns Promise<Blob>
177
- */
178
- toBlob(options) {
179
- return new Promise((resolve, reject) => {
180
- const format = options?.format || 'image/png';
181
- const quality = options?.quality;
182
- this.canvas.toBlob((blob) => {
183
- if (blob) {
184
- resolve(blob);
185
- }
186
- else {
187
- reject(new Error('Failed to create blob'));
188
- }
189
- }, format, quality);
190
- });
191
- }
192
- /**
193
- * 获取 ImageData
194
- * @returns ImageData
195
- */
196
- getImageData() {
197
- const ctx = this.canvas.getContext('2d');
198
- if (ctx) {
199
- return ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
200
- }
201
- // 如果是 WebGL 上下文,需要通过 readPixels 读取
202
- const gl = this.canvas.getContext('webgl');
203
- if (gl) {
204
- const pixels = new Uint8ClampedArray(this.canvas.width * this.canvas.height * 4);
205
- gl.readPixels(0, 0, this.canvas.width, this.canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
206
- return new ImageData(pixels, this.canvas.width, this.canvas.height);
207
- }
208
- throw new Error('Cannot get ImageData');
209
- }
210
- /**
211
- * 获取图像尺寸
212
- */
213
- getSize() {
214
- return {
215
- width: this.canvas.width,
216
- height: this.canvas.height,
217
- };
218
- }
219
- /**
220
- * 检查是否已加载图像
221
- */
222
- isLoaded() {
223
- return this.imageLoaded;
224
- }
225
- /**
226
- * 销毁资源
227
- */
228
- dispose() {
229
- this.disposeResources();
230
- this.imageLoaded = false;
231
- }
232
- // ===== 私有方法 =====
233
- getWebGLContext() {
234
- return this.canvas.getContext('webgl', {
235
- antialias: true,
236
- premultipliedAlpha: false,
237
- preserveDrawingBuffer: true,
238
- });
239
- }
240
- initFromImage(image) {
241
- const width = image.naturalWidth || image.width;
242
- const height = image.naturalHeight || image.height;
243
- this.canvas.width = width;
244
- this.canvas.height = height;
245
- const gl = this.getWebGLContext();
246
- if (!gl)
247
- throw new Error('WebGL not supported');
248
- this.disposeResources();
249
- gl.disable(gl.DEPTH_TEST);
250
- gl.viewport(0, 0, width, height);
251
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
252
- const sourceTexture = gl.createTexture();
253
- if (!sourceTexture)
254
- throw new Error('Failed to create texture');
255
- gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
256
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
257
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
258
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
259
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
260
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
261
- this.initResources(gl, width, height, sourceTexture);
262
- }
263
- initResources(gl, width, height, sourceTexture) {
264
- const blackPalette = createPaletteTexture(gl, buildBlackPalette(0));
265
- const positionBuffer = gl.createBuffer();
266
- const texCoordBuffer = gl.createBuffer();
267
- if (!positionBuffer || !texCoordBuffer) {
268
- throw new Error('Failed to create buffers');
269
- }
270
- gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
271
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
272
- gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
273
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]), gl.STATIC_DRAW);
274
- const programs = {
275
- pass: buildProgram(gl, shaders.vertexSource, shaders.passFragment, ['uTexture']),
276
- vibrance: buildProgram(gl, shaders.vertexSource, shaders.vibranceFragment, ['uTexture', 'uAmount']),
277
- saturation: buildProgram(gl, shaders.vertexSource, shaders.saturationFragment, ['uTexture', 'uMatrix[0]']),
278
- temperature: buildProgram(gl, shaders.vertexSource, shaders.temperatureFragment, ['uTexture', 'uAmount']),
279
- tint: buildProgram(gl, shaders.vertexSource, shaders.tintFragment, ['uTexture', 'uAmount']),
280
- hue: buildProgram(gl, shaders.vertexSource, shaders.hueFragment, ['uTexture', 'uRotation']),
281
- brightness: buildProgram(gl, shaders.vertexSource, shaders.brightnessFragment, ['uTexture', 'uAmount']),
282
- exposure: buildProgram(gl, shaders.vertexSource, shaders.exposureFragment, ['uTexture', 'uAmount']),
283
- contrast: buildProgram(gl, shaders.vertexSource, shaders.contrastFragment, ['uTexture', 'uMatrix[0]']),
284
- blacks: buildProgram(gl, shaders.blackVertexSource, shaders.blackPaletteFragment, [
285
- 'uTexture',
286
- 'uPaletteMap',
287
- 'transform',
288
- ]),
289
- whites: buildProgram(gl, shaders.vertexSource, shaders.whitesFragment, ['uTexture', 'uAmount']),
290
- highlights: buildProgram(gl, shaders.vertexSource, shaders.highlightsFragment, ['uTexture', 'uAmount']),
291
- shadows: buildProgram(gl, shaders.vertexSource, shaders.shadowsFragment, ['uTexture', 'uAmount']),
292
- dehaze: buildProgram(gl, shaders.vertexSource, shaders.dehazeFragment, ['uTexture', 'uAmount', 'uSize']),
293
- bloom: buildProgram(gl, shaders.vertexSource, shaders.bloomFragment, ['uTexture', 'uAmount', 'uTexel', 'uThreshold']),
294
- glamour: buildProgram(gl, shaders.vertexSource, shaders.glamourFragment, ['uTexture', 'uAmount', 'uTexel']),
295
- clarity: buildProgram(gl, shaders.vertexSource, shaders.clarityFragment, ['uTexture', 'uAmount', 'uTexel']),
296
- sharpen: buildProgram(gl, shaders.vertexSource, shaders.kernelFragment, ['uTexture', 'uTexel', 'uKernel[0]', 'uAmount']),
297
- smooth: buildProgram(gl, shaders.vertexSource, shaders.kernelFragment, ['uTexture', 'uTexel', 'uKernel[0]', 'uAmount']),
298
- blur: buildProgram(gl, shaders.vertexSource, shaders.blurFragment, ['uTexture', 'uSize']),
299
- vignette: buildProgram(gl, shaders.vertexSource, shaders.vignetteFragment, ['uTexture', 'uAmount', 'uSize']),
300
- grain: buildProgram(gl, shaders.vertexSource, shaders.grainFragment, ['uTexture', 'uResolution', 'uAmount', 'uTime']),
301
- };
302
- const targets = [
303
- createRenderTarget(gl, width, height),
304
- createRenderTarget(gl, width, height),
305
- ];
306
- this.resources = {
307
- gl,
308
- width,
309
- height,
310
- sourceTexture,
311
- blackPalette,
312
- quad: { positionBuffer, texCoordBuffer },
313
- programs,
314
- targets,
315
- };
316
- this.imageLoaded = true;
317
- this.render();
318
- }
319
- disposeResources() {
320
- if (!this.resources)
321
- return;
322
- const { gl, sourceTexture, blackPalette, quad, programs, targets } = this.resources;
323
- gl.deleteTexture(sourceTexture);
324
- gl.deleteTexture(blackPalette);
325
- gl.deleteBuffer(quad.positionBuffer);
326
- gl.deleteBuffer(quad.texCoordBuffer);
327
- targets.forEach((target) => {
328
- gl.deleteFramebuffer(target.framebuffer);
329
- gl.deleteTexture(target.texture);
330
- });
331
- Object.values(programs).forEach((programInfo) => {
332
- gl.deleteProgram(programInfo.program);
333
- });
334
- this.resources = null;
335
- }
336
- drawFrame(resources, settings) {
337
- const { gl, width, height, sourceTexture, blackPalette, quad, programs, targets, } = resources;
338
- gl.viewport(0, 0, width, height);
339
- const texel = [1 / width, 1 / height];
340
- let inputTexture = sourceTexture;
341
- let pingIndex = 0;
342
- const bindAttributes = (program) => {
343
- gl.bindBuffer(gl.ARRAY_BUFFER, quad.positionBuffer);
344
- const positionAttrib = program.attribs.aPosition >= 0
345
- ? program.attribs.aPosition
346
- : program.attribs.apos;
347
- if (positionAttrib >= 0) {
348
- gl.enableVertexAttribArray(positionAttrib);
349
- gl.vertexAttribPointer(positionAttrib, 2, gl.FLOAT, false, 0, 0);
350
- }
351
- gl.bindBuffer(gl.ARRAY_BUFFER, quad.texCoordBuffer);
352
- const texAttrib = program.attribs.aTexCoord >= 0
353
- ? program.attribs.aTexCoord
354
- : program.attribs.auv;
355
- if (texAttrib >= 0) {
356
- gl.enableVertexAttribArray(texAttrib);
357
- gl.vertexAttribPointer(texAttrib, 2, gl.FLOAT, false, 0, 0);
358
- }
359
- };
360
- const drawPass = (program, setupUniforms, output) => {
361
- gl.useProgram(program.program);
362
- bindAttributes(program);
363
- gl.activeTexture(gl.TEXTURE0);
364
- gl.bindTexture(gl.TEXTURE_2D, inputTexture);
365
- const textureLoc = program.uniforms.uTexture;
366
- if (textureLoc)
367
- gl.uniform1i(textureLoc, 0);
368
- setupUniforms();
369
- gl.bindFramebuffer(gl.FRAMEBUFFER, output ? output.framebuffer : null);
370
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
371
- inputTexture = output ? output.texture : inputTexture;
372
- };
373
- const swapTarget = () => {
374
- const target = targets[pingIndex % 2];
375
- pingIndex += 1;
376
- return target;
377
- };
378
- // Vibrance
379
- if (Math.abs(settings.vibrance) > 0.5) {
380
- drawPass(programs.vibrance, () => {
381
- gl.uniform1f(programs.vibrance.uniforms.uAmount, settings.vibrance / 100);
382
- }, swapTarget());
383
- }
384
- // Saturation
385
- if (Math.abs(settings.saturation) > 0.5) {
386
- drawPass(programs.saturation, () => {
387
- const matrix = buildSaturationMatrix(settings.saturation);
388
- gl.uniform1fv(programs.saturation.uniforms['uMatrix[0]'], matrix);
389
- }, swapTarget());
390
- }
391
- // Temperature
392
- if (Math.abs(settings.temperature) > 0.5) {
393
- drawPass(programs.temperature, () => {
394
- gl.uniform1f(programs.temperature.uniforms.uAmount, settings.temperature / 500);
395
- }, swapTarget());
396
- }
397
- // Tint
398
- if (Math.abs(settings.tint) > 0.5) {
399
- drawPass(programs.tint, () => {
400
- gl.uniform1f(programs.tint.uniforms.uAmount, settings.tint / 500);
401
- }, swapTarget());
402
- }
403
- // Hue
404
- if (Math.abs(settings.hue) > 0.5) {
405
- drawPass(programs.hue, () => {
406
- gl.uniform1f(programs.hue.uniforms.uRotation, settings.hue / 200);
407
- }, swapTarget());
408
- }
409
- // Brightness
410
- drawPass(programs.brightness, () => {
411
- gl.uniform1f(programs.brightness.uniforms.uAmount, settings.brightness / 200);
412
- }, swapTarget());
413
- // Exposure
414
- if (Math.abs(settings.exposure) > 0.5) {
415
- drawPass(programs.exposure, () => {
416
- gl.uniform1f(programs.exposure.uniforms.uAmount, settings.exposure / 100);
417
- }, swapTarget());
418
- }
419
- // Contrast
420
- if (Math.abs(settings.contrast) > 0.5) {
421
- drawPass(programs.contrast, () => {
422
- const matrix = buildContrastMatrix(settings.contrast);
423
- gl.uniform1fv(programs.contrast.uniforms['uMatrix[0]'], matrix);
424
- }, swapTarget());
425
- }
426
- // Blacks
427
- if (Math.abs(settings.blacks) > 0.5) {
428
- updatePaletteTexture(gl, blackPalette, buildBlackPalette(settings.blacks));
429
- drawPass(programs.blacks, () => {
430
- gl.activeTexture(gl.TEXTURE1);
431
- gl.bindTexture(gl.TEXTURE_2D, blackPalette);
432
- gl.uniform1i(programs.blacks.uniforms.uPaletteMap, 1);
433
- gl.uniform4f(programs.blacks.uniforms.transform, 1.0, 1.0, 0.0, 0.0);
434
- gl.activeTexture(gl.TEXTURE0);
435
- }, swapTarget());
436
- }
437
- // Whites
438
- if (Math.abs(settings.whites) > 0.5) {
439
- drawPass(programs.whites, () => {
440
- gl.uniform1f(programs.whites.uniforms.uAmount, settings.whites / 400);
441
- }, swapTarget());
442
- }
443
- // Highlights
444
- if (Math.abs(settings.highlights) > 0.5) {
445
- drawPass(programs.highlights, () => {
446
- gl.uniform1f(programs.highlights.uniforms.uAmount, settings.highlights / 100);
447
- }, swapTarget());
448
- }
449
- // Shadows
450
- if (Math.abs(settings.shadows) > 0.5) {
451
- drawPass(programs.shadows, () => {
452
- gl.uniform1f(programs.shadows.uniforms.uAmount, settings.shadows / 100);
453
- }, swapTarget());
454
- }
455
- // Dehaze
456
- if (Math.abs(settings.dehaze) > 0.5) {
457
- drawPass(programs.dehaze, () => {
458
- gl.uniform1f(programs.dehaze.uniforms.uAmount, settings.dehaze / 100);
459
- gl.uniform2f(programs.dehaze.uniforms.uSize, width, height);
460
- }, swapTarget());
461
- }
462
- // Bloom
463
- if (settings.bloom > 0.5) {
464
- drawPass(programs.bloom, () => {
465
- gl.uniform1f(programs.bloom.uniforms.uAmount, settings.bloom / 100);
466
- gl.uniform2f(programs.bloom.uniforms.uTexel, texel[0], texel[1]);
467
- gl.uniform1f(programs.bloom.uniforms.uThreshold, 0.5);
468
- }, swapTarget());
469
- }
470
- // Glamour
471
- if (settings.glamour > 0.5) {
472
- drawPass(programs.glamour, () => {
473
- gl.uniform1f(programs.glamour.uniforms.uAmount, settings.glamour / 100);
474
- gl.uniform2f(programs.glamour.uniforms.uTexel, texel[0], texel[1]);
475
- }, swapTarget());
476
- }
477
- // Clarity
478
- if (Math.abs(settings.clarity) > 0.5) {
479
- drawPass(programs.clarity, () => {
480
- gl.uniform1f(programs.clarity.uniforms.uAmount, settings.clarity / 100);
481
- gl.uniform2f(programs.clarity.uniforms.uTexel, texel[0], texel[1]);
482
- }, swapTarget());
483
- }
484
- // Sharpen
485
- if (settings.sharpen > 0.5) {
486
- drawPass(programs.sharpen, () => {
487
- gl.uniform2f(programs.sharpen.uniforms.uTexel, texel[0], texel[1]);
488
- gl.uniform1f(programs.sharpen.uniforms.uAmount, settings.sharpen / 100);
489
- gl.uniform1fv(programs.sharpen.uniforms['uKernel[0]'], new Float32Array([0, -1, 0, -1, 5, -1, 0, -1, 0]));
490
- }, swapTarget());
491
- }
492
- // Smooth
493
- if (settings.smooth > 0.5) {
494
- drawPass(programs.smooth, () => {
495
- gl.uniform2f(programs.smooth.uniforms.uTexel, texel[0], texel[1]);
496
- gl.uniform1f(programs.smooth.uniforms.uAmount, settings.smooth / 100);
497
- gl.uniform1fv(programs.smooth.uniforms['uKernel[0]'], new Float32Array([
498
- 1 / 9, 1 / 9, 1 / 9,
499
- 1 / 9, 1 / 9, 1 / 9,
500
- 1 / 9, 1 / 9, 1 / 9,
501
- ]));
502
- }, swapTarget());
503
- }
504
- // Blur (horizontal + vertical)
505
- const blurRadius = settings.blur;
506
- drawPass(programs.blur, () => {
507
- gl.uniform2f(programs.blur.uniforms.uSize, blurRadius / width, 0.0);
508
- }, swapTarget());
509
- drawPass(programs.blur, () => {
510
- gl.uniform2f(programs.blur.uniforms.uSize, 0.0, blurRadius / height);
511
- }, swapTarget());
512
- // Vignette
513
- drawPass(programs.vignette, () => {
514
- gl.uniform1f(programs.vignette.uniforms.uAmount, settings.vignette / 100);
515
- gl.uniform1f(programs.vignette.uniforms.uSize, 0.25);
516
- }, swapTarget());
517
- // Grain
518
- drawPass(programs.grain, () => {
519
- gl.uniform2f(programs.grain.uniforms.uResolution, width, height);
520
- gl.uniform1f(programs.grain.uniforms.uAmount, settings.grain / 800);
521
- gl.uniform1f(programs.grain.uniforms.uTime, 0);
522
- }, swapTarget());
523
- // Final pass to screen
524
- drawPass(programs.pass, () => { }, null);
525
- }
526
- }
527
- //# sourceMappingURL=processor.js.map