forked from phoboslab/jsmpeg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
canvas2d.js
119 lines (93 loc) · 2.81 KB
/
canvas2d.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
JSMpeg.Renderer.Canvas2D = (function(){ "use strict";
var CanvasRenderer = function(options) {
this.canvas = options.canvas || document.createElement('canvas');
this.width = this.canvas.width;
this.height = this.canvas.height;
this.enabled = true;
this.context = this.canvas.getContext('2d');
};
CanvasRenderer.prototype.destroy = function() {
// Nothing to do here
};
CanvasRenderer.prototype.resize = function(width, height) {
this.width = width|0;
this.height = height|0;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.imageData = this.context.getImageData(0, 0, this.width, this.height);
JSMpeg.Fill(this.imageData.data, 255);
};
CanvasRenderer.prototype.renderProgress = function(progress) {
var
w = this.canvas.width,
h = this.canvas.height,
ctx = this.context;
ctx.fillStyle = '#222';
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = '#fff';
ctx.fillRect(0, h - h * progress, w, h * progress);
};
CanvasRenderer.prototype.render = function(y, cb, cr) {
this.YCbCrToRGBA(y, cb, cr, this.imageData.data);
this.context.putImageData(this.imageData, 0, 0);
};
CanvasRenderer.prototype.YCbCrToRGBA = function(y, cb, cr, rgba) {
if (!this.enabled) {
return;
}
// Chroma values are the same for each block of 4 pixels, so we proccess
// 2 lines at a time, 2 neighboring pixels each.
// I wish we could use 32bit writes to the RGBA buffer instead of writing
// each byte separately, but we need the automatic clamping of the RGBA
// buffer.
var w = ((this.width + 15) >> 4) << 4,
w2 = w >> 1;
var yIndex1 = 0,
yIndex2 = w,
yNext2Lines = w + (w - this.width);
var cIndex = 0,
cNextLine = w2 - (this.width >> 1);
var rgbaIndex1 = 0,
rgbaIndex2 = this.width * 4,
rgbaNext2Lines = this.width * 4;
var cols = this.width >> 1,
rows = this.height >> 1;
var ccb, ccr, r, g, b;
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
ccb = cb[cIndex];
ccr = cr[cIndex];
cIndex++;
r = (ccb + ((ccb * 103) >> 8)) - 179;
g = ((ccr * 88) >> 8) - 44 + ((ccb * 183) >> 8) - 91;
b = (ccr + ((ccr * 198) >> 8)) - 227;
// Line 1
var y1 = y[yIndex1++];
var y2 = y[yIndex1++];
rgba[rgbaIndex1] = y1 + r;
rgba[rgbaIndex1+1] = y1 - g;
rgba[rgbaIndex1+2] = y1 + b;
rgba[rgbaIndex1+4] = y2 + r;
rgba[rgbaIndex1+5] = y2 - g;
rgba[rgbaIndex1+6] = y2 + b;
rgbaIndex1 += 8;
// Line 2
var y3 = y[yIndex2++];
var y4 = y[yIndex2++];
rgba[rgbaIndex2] = y3 + r;
rgba[rgbaIndex2+1] = y3 - g;
rgba[rgbaIndex2+2] = y3 + b;
rgba[rgbaIndex2+4] = y4 + r;
rgba[rgbaIndex2+5] = y4 - g;
rgba[rgbaIndex2+6] = y4 + b;
rgbaIndex2 += 8;
}
yIndex1 += yNext2Lines;
yIndex2 += yNext2Lines;
rgbaIndex1 += rgbaNext2Lines;
rgbaIndex2 += rgbaNext2Lines;
cIndex += cNextLine;
}
};
return CanvasRenderer;
})();