All files / src/lib/tiles readFileToTiles.ts

97.62% Statements 41/42
0% Branches 0/1
100% Functions 6/6
97.14% Lines 34/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 9931x 31x 31x 31x             31x                 31x       82x 82x 82x 82x     82x                       31x     2x 2x 2x 2x   2x 2x 10x 10x 10x     2x               31x     13x 13x               31x     41x 41x 41x 41x 605x 16211x                 16211x     41x    
import { TILE_SIZE } from "consts";
import { readFile } from "fs-extra";
import { PNG } from "pngjs";
import {
  ImageIndexFunction,
  IndexedImage,
  indexedImageTo2bppTileData,
  pixelDataToIndexedImage,
  sliceIndexedImage,
} from "shared/lib/tiles/indexedImage";
import { tileDataIndexFn } from "shared/lib/tiles/tileData";
 
/**
 * Load the given PNG image filename into an IndexedImage using the supplied index function.
 *
 * @param filename A local filename which is read using the NodeJS readFile method
 * @param indexFn Function to map an individual RGB pixel value to an 8-bit indexed value
 * @returns A new IndexedImage representing the image data provided
 */
export const readFileToIndexedImage = async (
  filename: string,
  indexFn: ImageIndexFunction,
): Promise<IndexedImage> => {
  const fileData = await readFile(filename);
  return new Promise((resolve, reject) => {
    new PNG().parse(fileData, (err, data) => {
      Iif (err) {
        return reject(err);
      }
      resolve(
        pixelDataToIndexedImage(data.width, data.height, data.data, indexFn),
      );
    });
  });
};
 
/**
 * Read an image filename into a GB 2bpp data array
 * @param filename Tiles image filename
 * @returns Uint8Array of 2bpp tile data
 */
export const readFileToTilesData = async (
  filename: string,
): Promise<Uint8Array> => {
  const img = await readFileToIndexedImage(filename, tileDataIndexFn);
  const tilesDataArray = indexedImageToTilesDataArray(img);
  const size = tilesDataArray.length * 16;
  const output = new Uint8Array(size);
 
  let index = 0;
  for (let ti = 0; ti < tilesDataArray.length; ti++) {
    const tileData = tilesDataArray[ti];
    output.set(tileData, index);
    index += tileData.length;
  }
 
  return output;
};
 
/**
 * Read an image filename into an array of GB 2bpp data array (one array per tile)
 * @param filename Tiles image filename
 * @returns Array of Uint8Array of 2bpp tile data
 */
export const readFileToTilesDataArray = async (
  filename: string,
): Promise<Uint8Array[]> => {
  const img = await readFileToIndexedImage(filename, tileDataIndexFn);
  return indexedImageToTilesDataArray(img);
};
 
/**
 * Convert an indexed image into an array of GB 2bpp data array (one array per tile)
 * @param filename Tiles image filename
 * @returns Array of Uint8Array of 2bpp tile data
 */
export const indexedImageToTilesDataArray = (
  img: IndexedImage,
): Uint8Array[] => {
  const xTiles = Math.floor(img.width / TILE_SIZE);
  const yTiles = Math.floor(img.height / TILE_SIZE);
  const output = [];
  for (let tyi = 0; tyi < yTiles; tyi++) {
    for (let txi = 0; txi < xTiles; txi++) {
      const tileData = indexedImageTo2bppTileData(
        sliceIndexedImage(
          img,
          txi * TILE_SIZE,
          tyi * TILE_SIZE,
          TILE_SIZE,
          TILE_SIZE,
        ),
      );
      output.push(tileData);
    }
  }
  return output;
};