diff --git a/api/lib/sprites.ts b/api/lib/sprites.ts index 998bc71fa..6ba426c35 100644 --- a/api/lib/sprites.ts +++ b/api/lib/sprites.ts @@ -3,6 +3,7 @@ import Vinyl from 'vinyl'; import { promisify } from 'node:util' import { Static } from '@sinclair/typebox'; import { IconResponse } from './types.js'; +import Sharp from 'sharp'; const SpriteSmith = promisify(spritesmith.run); @@ -12,15 +13,21 @@ type SpriteConfig = { }; export default async function(icons: Array>, config: SpriteConfig = {}) { - const doc = await SpriteSmith({ - src: icons.map((icon) => { - return new Vinyl({ - // @ts-expect-error Deal with indexing issue on icon - path: config.name ? icon[config.name] + '.png' : icon.path.replace(/.*?\//, ''), - contents: Buffer.from(config.useDataAlt && icon.data_alt ? icon.data_alt : icon.data, 'base64'), - }) - }) - }); + const src = []; + for (const icon of icons) { + const contents = await Sharp(Buffer.from(config.useDataAlt && icon.data_alt ? icon.data_alt : icon.data, 'base64')) + .resize(32) + .png() + .toBuffer(); + + src.push(new Vinyl({ + // @ts-expect-error Deal with indexing issue on icon + path: config.name ? icon[config.name] + '.png' : icon.path.replace(/.*?\//, ''), + contents + })) + } + + const doc = await SpriteSmith({ src }); const coords: Record = {}; for (const key in doc.coordinates) { diff --git a/api/routes/icons.ts b/api/routes/icons.ts index e65a193c4..a21450c86 100644 --- a/api/routes/icons.ts +++ b/api/routes/icons.ts @@ -478,6 +478,10 @@ export default async function router(schema: Schema, config: Config) { }), query: Type.Object({ token: Type.Optional(Type.String()), + alt: Type.Boolean({ + default: false, + description: 'Use alternate icon if possible' + }) }), description: 'Icon Data', }, async (req, res) => { @@ -493,7 +497,11 @@ export default async function router(schema: Schema, config: Config) { (${req.params.iconset} = iconset AND ${req.params.icon} = name) `); - res.status(200).send(Buffer.from(icon.data, 'base64')); + if (req.query.alt && icon.data_alt) { + res.status(200).send(Buffer.from(icon.data, 'base64')); + } else { + res.status(200).send(Buffer.from(icon.data, 'base64')); + } } catch (err) { Err.respond(err, res); } @@ -535,7 +543,9 @@ export default async function router(schema: Schema, config: Config) { ` }) - const sprites = await Sprites(icons.items); + const sprites = await Sprites(icons.items, { + useDataAlt: true + }); SpriteMap[req.query.iconset] = { image: sprites.image, json: sprites.json }; @@ -582,7 +592,9 @@ export default async function router(schema: Schema, config: Config) { AND ${scope} ` }) - const sprites = await Sprites(icons.items); + const sprites = await Sprites(icons.items, { + useDataAlt: true + }); SpriteMap[req.query.iconset] = { image: sprites.image, json: sprites.json }; diff --git a/api/web/src/components/CloudTAK/Map.vue b/api/web/src/components/CloudTAK/Map.vue index 58da2dc97..9e1d69a22 100644 --- a/api/web/src/components/CloudTAK/Map.vue +++ b/api/web/src/components/CloudTAK/Map.vue @@ -924,7 +924,7 @@ export default { // Eventually make a sprite URL part of the overlay so KMLs can load a sprite package const iconsets = await std('/api/iconset'); for (const iconset of iconsets.items) { - mapStore.map.addSprite(iconset.uid, String(stdurl(`/api/icon/sprite?token=${localStorage.token}&iconset=${iconset.uid}`))) + mapStore.map.addSprite(iconset.uid, String(stdurl(`/api/icon/sprite?token=${localStorage.token}&iconset=${iconset.uid}&alt=true`))) } await mapStore.initOverlays();