SpaceImageFormat.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. const { DeepClone } = require("../IntComp/common");
  2. const SpaceImageFormatLayer = require("./SpaceImageFormatLayer");
  3. module.exports = class SpaceImageFormat {
  4. /**
  5. * The Space Image Format
  6. *
  7. * @param {number} imageWidth The width of the image in pixels
  8. * @param {number} imageHeight The height of the image in pixels
  9. * @param {string} rawData The raw data for the complete SIF image
  10. */
  11. constructor(imageWidth, imageHeight, rawData) {
  12. this.width = imageWidth;
  13. this.height = imageHeight;
  14. /**
  15. * The layers of the image
  16. * @type {SpaceImageFormatLayer[]}
  17. */
  18. this.layers = this._parse(rawData);
  19. this.PIXEL_DEPTH = ["░", "▓"];
  20. }
  21. /**
  22. * Render an image to the console
  23. *
  24. * Given the simplicity of the image format's color space, we can easily
  25. * accomplish this using the "light shade" and "dark shade" ASCII characters.
  26. * @returns {void}
  27. */
  28. Render() {
  29. // Will be filled with a string containing the final image
  30. let renderedImage = "";
  31. // Get the first layer's rows
  32. let renderedLayerRows = DeepClone(this.layers[0].rows);
  33. // Iterate over subsequent layers
  34. for (let i = 1; i < this.layers.length; i++) {
  35. const layer = this.layers[i];
  36. for (let row = 0; row < renderedLayerRows.length; row++) {
  37. for (let column = 0; column < renderedLayerRows[row].length; column++) {
  38. if (renderedLayerRows[row][column] == 2 && layer.rows[row][column] !== 2) { renderedLayerRows[row][column] = layer.rows[row][column]; }
  39. }
  40. }
  41. // Check if all transparent pixels have been filled in
  42. if (renderedLayerRows.flat(Infinity).indexOf(2) == -1) { break; }
  43. }
  44. // Convert each row from an array of 0's and 1's to a string
  45. renderedLayerRows = renderedLayerRows.map((row) => row.map((pixelValue) => this.PIXEL_DEPTH[pixelValue]).join(""));
  46. // Join all rows with new lines to complete the image
  47. renderedImage = renderedLayerRows.join("\n");
  48. console.log(renderedImage);
  49. }
  50. /**
  51. * Parse raw data in order to build the SIF layers
  52. *
  53. * @param {string} rawData The raw data of the image
  54. * @returns {SpaceImageFormatLayer[]} The layers of an SIF image
  55. */
  56. _parse(rawData) {
  57. const layers = [];
  58. const layerSize = this.width * this.height;
  59. const layerSplit = new RegExp(`(\\d{${layerSize}})`, "g");
  60. const tempLayers = rawData.split(layerSplit).filter((l) => !!l);
  61. tempLayers.forEach((layerData) => {
  62. layers.push(new SpaceImageFormatLayer(this.width, this.height, layerData));
  63. });
  64. return layers;
  65. }
  66. };