FrequencyDistribution.mjs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /**
  2. * @author n1474335 [n1474335@gmail.com]
  3. * @copyright Crown Copyright 2016
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation";
  7. import Utils from "../Utils";
  8. import OperationError from "../errors/OperationError";
  9. /**
  10. * Frequency distribution operation
  11. */
  12. class FrequencyDistribution extends Operation {
  13. /**
  14. * FrequencyDistribution constructor
  15. */
  16. constructor() {
  17. super();
  18. this.name = "Frequency distribution";
  19. this.module = "Default";
  20. this.description = "Displays the distribution of bytes in the data as a graph.";
  21. this.infoURL = "https://wikipedia.org/wiki/Frequency_distribution";
  22. this.inputType = "ArrayBuffer";
  23. this.outputType = "json";
  24. this.presentType = "html";
  25. this.args = [
  26. {
  27. "name": "Show 0%s",
  28. "type": "boolean",
  29. "value": "Entropy.FREQ_ZEROS"
  30. }
  31. ];
  32. }
  33. /**
  34. * @param {ArrayBuffer} input
  35. * @param {Object[]} args
  36. * @returns {json}
  37. */
  38. run(input, args) {
  39. const data = new Uint8Array(input);
  40. if (!data.length) throw new OperationError("No data");
  41. const distrib = new Array(256).fill(0),
  42. percentages = new Array(256),
  43. len = data.length;
  44. let i;
  45. // Count bytes
  46. for (i = 0; i < len; i++) {
  47. distrib[data[i]]++;
  48. }
  49. // Calculate percentages
  50. let repr = 0;
  51. for (i = 0; i < 256; i++) {
  52. if (distrib[i] > 0) repr++;
  53. percentages[i] = distrib[i] / len * 100;
  54. }
  55. return {
  56. "dataLength": len,
  57. "percentages": percentages,
  58. "distribution": distrib,
  59. "bytesRepresented": repr
  60. };
  61. }
  62. /**
  63. * Displays the frequency distribution as a bar chart for web apps.
  64. *
  65. * @param {json} freq
  66. * @returns {html}
  67. */
  68. present(freq, args) {
  69. const showZeroes = args[0];
  70. // Print
  71. let output = `<canvas id='chart-area'></canvas><br>
  72. Total data length: ${freq.dataLength}
  73. Number of bytes represented: ${freq.bytesRepresented}
  74. Number of bytes not represented: ${256 - freq.bytesRepresented}
  75. Byte Percentage
  76. <script>
  77. var canvas = document.getElementById("chart-area"),
  78. parentRect = canvas.parentNode.getBoundingClientRect(),
  79. scores = ${JSON.stringify(freq.percentages)};
  80. canvas.width = parentRect.width * 0.95;
  81. canvas.height = parentRect.height * 0.9;
  82. CanvasComponents.drawBarChart(canvas, scores, "Byte", "Frequency %", 16, 6);
  83. </script>`;
  84. for (let i = 0; i < 256; i++) {
  85. if (freq.distribution[i] || showZeroes) {
  86. output += " " + Utils.hex(i, 2) + " (" +
  87. (freq.percentages[i].toFixed(2).replace(".00", "") + "%)").padEnd(8, " ") +
  88. Array(Math.ceil(freq.percentages[i])+1).join("|") + "\n";
  89. }
  90. }
  91. return output;
  92. }
  93. }
  94. export default FrequencyDistribution;