Skip to content

Commit

Permalink
chore(graph-layers): Clean up lint and tsc errors for pack-images script
Browse files Browse the repository at this point in the history
  • Loading branch information
donmccurdy committed Apr 15, 2024
1 parent a97ca5f commit ae61618
Show file tree
Hide file tree
Showing 12 changed files with 765 additions and 615 deletions.
123 changes: 123 additions & 0 deletions modules/graph-layers/scripts/pack-marker-images.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* Generate texture atlas from images
* ```
* # default input/output
* npx tsx ./pack-marker-images.ts
*
* # custom input/output directories
* npx tsx ./pack-marker-images.ts [inputDir] [outputDir]
* ```
*/

import {readFile, writeFile, readdir} from 'node:fs/promises';
import {dirname, join, resolve} from 'node:path';
import { fileURLToPath } from 'node:url';
import ndarray, {NdArray} from 'ndarray';
import {getPixels, savePixels} from 'ndarray-pixels';
import pack from 'bin-pack';
import Datauri from 'datauri';

const __dirname = dirname(fileURLToPath(import.meta.url));
const packageRoot = join(__dirname, '..');

const inputDir = process.argv[2] || 'src/layers/common-layers/marker-layer/markers/';
const outputDir = process.argv[3] || 'src/layers/common-layers/marker-layer/';

const INPUT_DIR = resolve(packageRoot, inputDir);
const OUTPUT_IMAGE = resolve(packageRoot, outputDir, 'marker-atlas.png');
const OUTPUT_MAPPING = resolve(packageRoot, outputDir, `marker-mapping.ts`);
const OUTPUT_DATA_URL = resolve(packageRoot, outputDir, 'atlas-data-url.ts');
const OUTPUT_LIST = resolve(packageRoot, outputDir, 'marker-list.ts');
const IMAGE_PATTERN = /\.(png|jpg|jpeg|gif|bmp|tiff)$/i;

// Get all images in the input path
const fileNames = (await readdir(INPUT_DIR)).filter((name) => IMAGE_PATTERN.test(name));

Promise.all(fileNames.map((name: string) => readImage(resolve(INPUT_DIR, name)))).then(async (images) => {
// Images are loaded
const nodes = images.map((pixels: NdArray, index: number) => ({
name: fileNames[index],
pixels,
width: pixels.shape[0],
height: pixels.shape[1]
}));

// Bin pack
const result = pack(nodes);
// console.log(result.items.length + ' items packed.');

// Convert to texture atlas
const outputJSON = {};
const outputImage = createImage(result.width, result.height);
result.items.forEach((item) => {
outputJSON[item.item.name.replace(IMAGE_PATTERN, '')] = {
x: item.x,
y: item.y,
width: item.width,
height: item.height,
mask: true
};
copyPixels(item.item.pixels, outputImage, item.x, item.y);
});

// Write to disk
await writeMapping(OUTPUT_MAPPING, outputJSON);
await writeImage(OUTPUT_IMAGE, outputImage, () => writeDataURL(OUTPUT_IMAGE, OUTPUT_DATA_URL));
await writeList(OUTPUT_LIST, outputJSON);
});

/* Utils */

function copyPixels(fromImage: NdArray, toImage: NdArray, x: number, y: number): void {
const width = fromImage.shape[0];
const height = fromImage.shape[1];
const channels = fromImage.shape[2];

for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
for (let k = 0; k < channels; k++) {
const value = fromImage.get(i, j, k);
toImage.set(i + x, j + y, k, value);
}
}
}
}

async function writeMapping(filePath: string, content: unknown): Promise<void> {
await exportJSFile(filePath, 'MarkerMapping', JSON.stringify(content, null, 2));
}

function createImage(width: number, height: number): NdArray<Uint8ClampedArray> {
return ndarray(new Uint8ClampedArray(width * height * 4), [width, height, 4]);
}

async function writeDataURL(imagePath: string, outputFilePath: string): Promise<void> {
const content = {dataURL: await Datauri(imagePath)};
await exportJSFile(outputFilePath, 'AtlasDataURL', JSON.stringify(content, null, 2));
}

async function writeList(filePath: string, content: object): Promise<void> {
const markers = Object.keys(content);
const markerMap = markers.reduce((res, marker) => {
res[marker] = marker;
return res;
}, {});
const contentStr = JSON.stringify(markerMap, null, 2);
await exportJSFile(filePath, 'MarkerList', contentStr);
}

async function exportJSFile(filePath: string, exportName: string, contentStr: string): Promise<void> {
await writeFile(
filePath,
`/* eslint-disable */\nexport const ${exportName} = ${contentStr};\n/* eslint-enable */\n`
);
}

async function readImage(filePath: string): Promise<NdArray> {
return readFile(filePath).then((buffer) => getPixels(buffer, 'image/png'));
}

async function writeImage(filePath: string, pixelArr: NdArray<Uint8ClampedArray>, createDataURL: () => void): Promise<void> {
await writeFile(filePath, await savePixels(pixelArr, 'image/png'));
createDataURL();
}

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @noflow
import {CompositeLayer} from '@deck.gl/core';
import {IconLayer} from '@deck.gl/layers';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
/* eslint-disable */
export const MarkerList = {
'location-marker-filled': 'location-marker-filled',
'bell-filled': 'bell-filled',
'bookmark-filled': 'bookmark-filled',
bookmark: 'bookmark',
'cd-filled': 'cd-filled',
cd: 'cd',
checkmark: 'checkmark',
'circle-check-filled': 'circle-check-filled',
'circle-check': 'circle-check',
'circle-filled': 'circle-filled',
'circle-i-filled': 'circle-i-filled',
'circle-i': 'circle-i',
'circle-minus-filled': 'circle-minus-filled',
'circle-minus': 'circle-minus',
'circle-plus-filled': 'circle-plus-filled',
'circle-plus': 'circle-plus',
'circle-questionmark-filled': 'circle-questionmark-filled',
'circle-questionmark': 'circle-questionmark',
'circle-slash-filled': 'circle-slash-filled',
'circle-slash': 'circle-slash',
'circle-x-filled': 'circle-x-filled',
'circle-x': 'circle-x',
circle: 'circle',
'diamond-filled': 'diamond-filled',
diamond: 'diamond',
'flag-filled': 'flag-filled',
flag: 'flag',
gear: 'gear',
'heart-filled': 'heart-filled',
heart: 'heart',
bell: 'bell',
'location-marker': 'location-marker',
'octagonal-star-filled': 'octagonal-star-filled',
'octagonal-star': 'octagonal-star',
'person-filled': 'person-filled',
person: 'person',
'pin-filled': 'pin-filled',
pin: 'pin',
'plus-small': 'plus-small',
plus: 'plus',
'rectangle-filled': 'rectangle-filled',
rectangle: 'rectangle',
'star-filled': 'star-filled',
star: 'star',
'tag-filled': 'tag-filled',
tag: 'tag',
'thumb-down-filled': 'thumb-down-filled',
'thumb-down': 'thumb-down',
'thumb-up': 'thumb-up',
'thumb_up-filled': 'thumb_up-filled',
'triangle-down-filled': 'triangle-down-filled',
'triangle-down': 'triangle-down',
'triangle-left-filled': 'triangle-left-filled',
'triangle-left': 'triangle-left',
'triangle-right-filled': 'triangle-right-filled',
'triangle-right': 'triangle-right',
'triangle-up-filled': 'triangle-up-filled',
'triangle-up': 'triangle-up',
'x-small': 'x-small',
x: 'x'
"bell-filled": "bell-filled",
"bell": "bell",
"bookmark-filled": "bookmark-filled",
"bookmark": "bookmark",
"cd-filled": "cd-filled",
"cd": "cd",
"checkmark": "checkmark",
"circle-check-filled": "circle-check-filled",
"circle-check": "circle-check",
"circle-filled": "circle-filled",
"circle-i-filled": "circle-i-filled",
"circle-i": "circle-i",
"circle-minus-filled": "circle-minus-filled",
"circle-minus": "circle-minus",
"circle-plus-filled": "circle-plus-filled",
"circle-plus": "circle-plus",
"circle-questionmark-filled": "circle-questionmark-filled",
"circle-questionmark": "circle-questionmark",
"circle-slash-filled": "circle-slash-filled",
"circle-slash": "circle-slash",
"circle-x-filled": "circle-x-filled",
"circle-x": "circle-x",
"circle": "circle",
"diamond-filled": "diamond-filled",
"diamond": "diamond",
"flag-filled": "flag-filled",
"flag": "flag",
"gear": "gear",
"heart-filled": "heart-filled",
"heart": "heart",
"location-marker-filled": "location-marker-filled",
"location-marker": "location-marker",
"octagonal-star-filled": "octagonal-star-filled",
"octagonal-star": "octagonal-star",
"person-filled": "person-filled",
"person": "person",
"pin-filled": "pin-filled",
"pin": "pin",
"plus-small": "plus-small",
"plus": "plus",
"rectangle-filled": "rectangle-filled",
"rectangle": "rectangle",
"star-filled": "star-filled",
"star": "star",
"tag-filled": "tag-filled",
"tag": "tag",
"thumb-down-filled": "thumb-down-filled",
"thumb-down": "thumb-down",
"thumb-up": "thumb-up",
"thumb_up-filled": "thumb_up-filled",
"triangle-down-filled": "triangle-down-filled",
"triangle-down": "triangle-down",
"triangle-left-filled": "triangle-left-filled",
"triangle-left": "triangle-left",
"triangle-right-filled": "triangle-right-filled",
"triangle-right": "triangle-right",
"triangle-up-filled": "triangle-up-filled",
"triangle-up": "triangle-up",
"x-small": "x-small",
"x": "x"
};
/* eslint-enable */
Loading

0 comments on commit ae61618

Please sign in to comment.