-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
2d_backend.class.ts
65 lines (63 loc) · 2.29 KB
/
2d_backend.class.ts
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
/**
* Canvas 2D filter backend.
*/
import type { BaseFilter } from './base_filter.class';
import { T2DPipelineState, TPipelineResources } from './typedefs';
export class Canvas2dFilterBackend {
/**
* Experimental. This object is a sort of repository of help layers used to avoid
* of recreating them during frequent filtering. If you are previewing a filter with
* a slider you probably do not want to create help layers every filter step.
* in this object there will be appended some canvases, created once, resized sometimes
* cleared never. Clearing is left to the developer.
**/
resources: TPipelineResources = {};
/**
* Apply a set of filters against a source image and draw the filtered output
* to the provided destination canvas.
*
* @param {EnhancedFilter} filters The filter to apply.
* @param {HTMLImageElement|HTMLCanvasElement} sourceElement The source to be filtered.
* @param {Number} sourceWidth The width of the source input.
* @param {Number} sourceHeight The height of the source input.
* @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.
*/
applyFilters(
filters: BaseFilter[],
sourceElement: CanvasImageSource,
sourceWidth: number,
sourceHeight: number,
targetCanvas: HTMLCanvasElement
): T2DPipelineState | void {
const ctx = targetCanvas.getContext('2d');
if (!ctx) {
return;
}
ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight);
const imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);
const originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);
const pipelineState: T2DPipelineState = {
sourceWidth,
sourceHeight,
imageData,
originalEl: sourceElement,
originalImageData,
canvasEl: targetCanvas,
ctx,
filterBackend: this,
};
filters.forEach((filter) => {
filter.applyTo(pipelineState);
});
const { imageData: imageDataPostFilter } = pipelineState;
if (
imageDataPostFilter.width !== sourceWidth ||
imageDataPostFilter.height !== sourceHeight
) {
targetCanvas.width = imageDataPostFilter.width;
targetCanvas.height = imageDataPostFilter.height;
}
ctx.putImageData(imageDataPostFilter, 0, 0);
return pipelineState;
}
}