const { DeepClone } = require("../IntComp/common"); const SpaceImageFormatLayer = require("./SpaceImageFormatLayer"); module.exports = class SpaceImageFormat { /** * The Space Image Format * * @param {number} imageWidth The width of the image in pixels * @param {number} imageHeight The height of the image in pixels * @param {string} rawData The raw data for the complete SIF image */ constructor(imageWidth, imageHeight, rawData) { this.width = imageWidth; this.height = imageHeight; /** * The layers of the image * @type {SpaceImageFormatLayer[]} */ this.layers = this._parse(rawData); this.PIXEL_DEPTH = ["░", "▓"]; } /** * Render an image to the console * * Given the simplicity of the image format's color space, we can easily * accomplish this using the "light shade" and "dark shade" ASCII characters. * @returns {void} */ Render() { // Will be filled with a string containing the final image let renderedImage = ""; // Get the first layer's rows let renderedLayerRows = DeepClone(this.layers[0].rows); // Iterate over subsequent layers for (let i = 1; i < this.layers.length; i++) { const layer = this.layers[i]; for (let row = 0; row < renderedLayerRows.length; row++) { for (let column = 0; column < renderedLayerRows[row].length; column++) { if (renderedLayerRows[row][column] == 2 && layer.rows[row][column] !== 2) { renderedLayerRows[row][column] = layer.rows[row][column]; } } } // Check if all transparent pixels have been filled in if (renderedLayerRows.flat(Infinity).indexOf(2) == -1) { break; } } // Convert each row from an array of 0's and 1's to a string renderedLayerRows = renderedLayerRows.map((row) => row.map((pixelValue) => this.PIXEL_DEPTH[pixelValue]).join("")); // Join all rows with new lines to complete the image renderedImage = renderedLayerRows.join("\n"); console.log(renderedImage); } /** * Parse raw data in order to build the SIF layers * * @param {string} rawData The raw data of the image * @returns {SpaceImageFormatLayer[]} The layers of an SIF image */ _parse(rawData) { const layers = []; const layerSize = this.width * this.height; const layerSplit = new RegExp(`(\\d{${layerSize}})`, "g"); const tempLayers = rawData.split(layerSplit).filter((l) => !!l); tempLayers.forEach((layerData) => { layers.push(new SpaceImageFormatLayer(this.width, this.height, layerData)); }); return layers; } };