flux-klein-web / src /lib /sizes.js
radames's picture
initial commit
9c78030
Raw
History Blame Contribute Delete
2.16 kB
// Output sizes: any side 128…1024 in steps of 16; these are the presets on the menu. The app
// shows only the ones inside the engine's limits (max side and area budget, App.svelte), so the
// list can run ahead of what a given build accepts. The examples' desktop and mobile sizes
// (examples.js) are all listed here.
export const SIZES = [
[128, 128],
[256, 256],
[384, 384],
[512, 512],
[640, 640],
[768, 768],
[1024, 1024],
[320, 192],
[192, 320],
[480, 288],
[288, 480],
[384, 256],
[256, 384],
[480, 320],
[320, 480],
[512, 256],
[256, 512],
[448, 256],
[256, 448],
[768, 512],
[512, 768],
[960, 640],
[640, 960],
[1024, 576],
[576, 1024],
[1024, 768],
[768, 1024],
[1024, 512],
[512, 1024],
]
export const sizeKey = ([w, h]) => `${w}x${h}`
export const parseSize = (k) => k.split('x').map(Number)
// The preset closest to an image's aspect (then closest in area to the current one), within budget.
export function fitToAspect(w0, h0, sizes, current) {
const want = Math.log(w0 / h0),
cur = current[0] * current[1]
let best = null
for (const s of sizes) {
const err = Math.abs(Math.log(s[0] / s[1]) - want),
area = Math.abs(s[0] * s[1] - cur)
if (!best || err < best.err - 1e-9 || (Math.abs(err - best.err) < 1e-9 && area < best.area))
best = { s, err, area }
}
return best?.s ?? current
}
const gcd = (a, b) => (b ? gcd(b, a % b) : a)
export const ratioLabel = ([w, h]) => {
const g = gcd(w, h)
return `${w / g}:${h / g}`
}
export const orientation = ([w, h]) => (w === h ? 'Square' : w < h ? 'Portrait' : 'Landscape')
// Menu order: tallest first, widest last, smallest before largest within one shape. Listed that
// way the presets read as a fan, so "taller / wider / bigger" is answered by position alone.
export const byShape = (a, b) => a[0] * b[1] - b[0] * a[1] || a[0] * a[1] - b[0] * b[1]
// Longest side among a list of presets — the scale the menu's little rectangles are drawn
// against, so a glyph shows the real proportions *and* the real size next to its neighbours.
export const longestSide = (sizes) => Math.max(...sizes.flat(), 1)