predictor.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. function decodeRowAcc(row, stride) {
  2. let length = row.length - stride;
  3. let offset = 0;
  4. do {
  5. for (let i = stride; i > 0; i--) {
  6. row[offset + stride] += row[offset];
  7. offset++;
  8. }
  9. length -= stride;
  10. } while (length > 0);
  11. }
  12. function decodeRowFloatingPoint(row, stride, bytesPerSample) {
  13. let index = 0;
  14. let count = row.length;
  15. const wc = count / bytesPerSample;
  16. while (count > stride) {
  17. for (let i = stride; i > 0; --i) {
  18. row[index + stride] += row[index];
  19. ++index;
  20. }
  21. count -= stride;
  22. }
  23. const copy = row.slice();
  24. for (let i = 0; i < wc; ++i) {
  25. for (let b = 0; b < bytesPerSample; ++b) {
  26. row[(bytesPerSample * i) + b] = copy[((bytesPerSample - b - 1) * wc) + i];
  27. }
  28. }
  29. }
  30. export function applyPredictor(block, predictor, width, height, bitsPerSample,
  31. planarConfiguration) {
  32. if (!predictor || predictor === 1) {
  33. return block;
  34. }
  35. for (let i = 0; i < bitsPerSample.length; ++i) {
  36. if (bitsPerSample[i] % 8 !== 0) {
  37. throw new Error('When decoding with predictor, only multiple of 8 bits are supported.');
  38. }
  39. if (bitsPerSample[i] !== bitsPerSample[0]) {
  40. throw new Error('When decoding with predictor, all samples must have the same size.');
  41. }
  42. }
  43. const bytesPerSample = bitsPerSample[0] / 8;
  44. const stride = planarConfiguration === 2 ? 1 : bitsPerSample.length;
  45. for (let i = 0; i < height; ++i) {
  46. // Last strip will be truncated if height % stripHeight != 0
  47. if (i * stride * width * bytesPerSample >= block.byteLength) {
  48. break;
  49. }
  50. let row;
  51. if (predictor === 2) { // horizontal prediction
  52. switch (bitsPerSample[0]) {
  53. case 8:
  54. row = new Uint8Array(
  55. block, i * stride * width * bytesPerSample, stride * width * bytesPerSample,
  56. );
  57. break;
  58. case 16:
  59. row = new Uint16Array(
  60. block, i * stride * width * bytesPerSample, stride * width * bytesPerSample / 2,
  61. );
  62. break;
  63. case 32:
  64. row = new Uint32Array(
  65. block, i * stride * width * bytesPerSample, stride * width * bytesPerSample / 4,
  66. );
  67. break;
  68. default:
  69. throw new Error(`Predictor 2 not allowed with ${bitsPerSample[0]} bits per sample.`);
  70. }
  71. decodeRowAcc(row, stride, bytesPerSample);
  72. } else if (predictor === 3) { // horizontal floating point
  73. row = new Uint8Array(
  74. block, i * stride * width * bytesPerSample, stride * width * bytesPerSample,
  75. );
  76. decodeRowFloatingPoint(row, stride, bytesPerSample);
  77. }
  78. }
  79. return block;
  80. }