canvas2d.js 2.7KB

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