All files / src/lib/tiles readFileToTiles.ts

97.61% Statements 41/42
50% Branches 1/2
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 9966x 66x 66x 66x             66x                 66x       163x 163x 163x 163x     163x                       66x     16x 16x 16x 16x   16x 16x 80x 80x 80x     16x               66x     44x 44x               66x     101x 101x 101x 101x 1210x 31458x                 31458x     101x    
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;
};