canvas2d.js 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. JSMpeg.Renderer.Canvas2D = (function(){ "use strict";
  2. var CanvasRenderer = function(options) {
  3. this.canvas = options.canvas || document.createElement('canvas');
  4. this.width = this.canvas.width;
  5. this.height = this.canvas.height;
  6. this.enabled = true;
  7. this.context = this.canvas.getContext('2d');
  8. };
  9. CanvasRenderer.prototype.destroy = function() {
  10. // Nothing to do here
  11. };
  12. CanvasRenderer.prototype.resize = function(width, height) {
  13. this.width = width|0;
  14. this.height = height|0;
  15. this.canvas.width = this.width;
  16. this.canvas.height = this.height;
  17. this.imageData = this.context.getImageData(0, 0, this.width, this.height);
  18. JSMpeg.Fill(this.imageData.data, 255);
  19. };
  20. CanvasRenderer.prototype.renderProgress = function(progress) {
  21. var
  22. w = this.canvas.width,
  23. h = this.canvas.height,
  24. ctx = this.context;
  25. ctx.fillStyle = '#222';
  26. ctx.fillRect(0, 0, w, h);
  27. ctx.fillStyle = '#fff';
  28. ctx.fillRect(0, h - h * progress, w, h * progress);
  29. };
  30. CanvasRenderer.prototype.render = function(y, cb, cr) {
  31. this.YCbCrToRGBA(y, cb, cr, this.imageData.data);
  32. this.context.putImageData(this.imageData, 0, 0);
  33. };
  34. CanvasRenderer.prototype.YCbCrToRGBA = function(y, cb, cr, rgba) {
  35. if (!this.enabled) {
  36. return;
  37. }
  38. // Chroma values are the same for each block of 4 pixels, so we proccess
  39. // 2 lines at a time, 2 neighboring pixels each.
  40. // I wish we could use 32bit writes to the RGBA buffer instead of writing
  41. // each byte separately, but we need the automatic clamping of the RGBA
  42. // buffer.
  43. var w = ((this.width + 15) >> 4) << 4,
  44. w2 = w >> 1;
  45. var yIndex1 = 0,
  46. yIndex2 = w,
  47. yNext2Lines = w + (w - this.width);
  48. var cIndex = 0,
  49. cNextLine = w2 - (this.width >> 1);
  50. var rgbaIndex1 = 0,
  51. rgbaIndex2 = this.width * 4,
  52. rgbaNext2Lines = this.width * 4;
  53. var cols = this.width >> 1,
  54. rows = this.height >> 1;
  55. var ccb, ccr, r, g, b;
  56. for (var row = 0; row < rows; row++) {
  57. for (var col = 0; col < cols; col++) {
  58. ccb = cb[cIndex];
  59. ccr = cr[cIndex];
  60. cIndex++;
  61. r = (ccb + ((ccb * 103) >> 8)) - 179;
  62. g = ((ccr * 88) >> 8) - 44 + ((ccb * 183) >> 8) - 91;
  63. b = (ccr + ((ccr * 198) >> 8)) - 227;
  64. // Line 1
  65. var y1 = y[yIndex1++];
  66. var y2 = y[yIndex1++];
  67. rgba[rgbaIndex1] = y1 + r;
  68. rgba[rgbaIndex1+1] = y1 - g;
  69. rgba[rgbaIndex1+2] = y1 + b;
  70. rgba[rgbaIndex1+4] = y2 + r;
  71. rgba[rgbaIndex1+5] = y2 - g;
  72. rgba[rgbaIndex1+6] = y2 + b;
  73. rgbaIndex1 += 8;
  74. // Line 2
  75. var y3 = y[yIndex2++];
  76. var y4 = y[yIndex2++];
  77. rgba[rgbaIndex2] = y3 + r;
  78. rgba[rgbaIndex2+1] = y3 - g;
  79. rgba[rgbaIndex2+2] = y3 + b;
  80. rgba[rgbaIndex2+4] = y4 + r;
  81. rgba[rgbaIndex2+5] = y4 - g;
  82. rgba[rgbaIndex2+6] = y4 + b;
  83. rgbaIndex2 += 8;
  84. }
  85. yIndex1 += yNext2Lines;
  86. yIndex2 += yNext2Lines;
  87. rgbaIndex1 += rgbaNext2Lines;
  88. rgbaIndex2 += rgbaNext2Lines;
  89. cIndex += cNextLine;
  90. }
  91. };
  92. return CanvasRenderer;
  93. })();