cozy-iiif
Version:
A developer-friendly collection of abstractions and utilities built on top of @iiif/presentation-3 and @iiif/parser
188 lines (187 loc) • 6.09 kB
JavaScript
import "image-size";
import { g as $ } from "../resource-DS2brz47.js";
const F = (t) => ({ id: $(t, "id"), ...t }), T = (t) => fetch(t.serviceUrl).then((e) => e.json()).then(F), P = new FinalizationRegistry(({ signal: t, aborted: e }) => {
t == null || t.removeEventListener("abort", e);
});
function M({ limit: t, interval: e, strict: c, signal: i, onDelay: r }) {
if (!Number.isFinite(t))
throw new TypeError("Expected `limit` to be a finite number");
if (!Number.isFinite(e))
throw new TypeError("Expected `interval` to be a finite number");
const n = /* @__PURE__ */ new Map();
let o = 0, a = 0;
function l() {
const h = Date.now();
return h - o > e ? (a = 1, o = h, 0) : (a < t ? a++ : (o += e, a = 1), o - h);
}
const s = [];
function d() {
const h = Date.now();
if (s.length > 0 && h - s.at(-1) > e && (s.length = 0), s.length < t)
return s.push(h), 0;
const w = s[0] + e;
return s.shift(), s.push(w), Math.max(0, w - h);
}
const g = c ? d : l;
return (h) => {
const w = function(...u) {
if (!w.isEnabled)
return (async () => h.apply(this, u))();
let f;
return new Promise((v, C) => {
const y = () => {
v(h.apply(this, u)), n.delete(f);
}, p = g();
p > 0 ? (f = setTimeout(y, p), n.set(f, C), r == null || r(...u)) : y();
});
}, m = () => {
for (const u of n.keys())
clearTimeout(u), n.get(u)(i.reason);
n.clear(), s.splice(0, s.length);
};
return P.register(w, { signal: i, aborted: m }), i == null || i.throwIfAborted(), i == null || i.addEventListener("abort", m, { once: !0 }), w.isEnabled = !0, Object.defineProperty(w, "queueSize", {
get() {
return n.size;
}
}), w;
};
}
const H = () => {
let t = {
limit: 5,
interval: 1e3
}, e = M(t);
return {
getInstance: () => e,
getConfig: () => ({ ...t }),
setConfig: (n) => {
t = { ...t, ...n }, e = M(t);
}
};
}, x = H(), W = (t) => {
if (!t) return;
const e = x.getConfig();
(t.limit && t.limit !== e.limit || t.interval && t.interval !== e.interval) && x.setConfig({ ...e, ...t });
}, E = (t) => {
if (t) {
const i = {
limit: t.callsPerSecond || 5,
interval: 1e3
};
W(i);
}
return { loadImage: x.getInstance()((i) => new Promise((r, n) => {
const o = new Image();
o.crossOrigin = "anonymous", o.onload = () => r(o), o.onerror = n, o.src = i;
})) };
}, j = (t, e) => {
const { x: c, y: i, w: r, h: n } = e, o = t.tiles[0].width, a = t.tiles[0].height || t.tiles[0].width;
return `${t.id}/${c * o},${i * a},${r},${n}/${o},/0/default.jpg`;
}, R = (t, e) => {
const c = t.tiles[0].width, i = t.tiles[0].height || t.tiles[0].width, r = t.width, n = t.height, o = Math.floor(e.x / c), a = Math.floor(e.y / i), l = Math.ceil((e.x + e.w) / c), s = Math.ceil((e.y + e.h) / i), d = [];
for (let g = a; g < s; g++)
for (let h = o; h < l; h++) {
if (h * c >= r || g * i >= n)
continue;
const w = Math.min(c, r - h * c), m = Math.min(i, n - g * i);
d.push({
x: h,
y: g,
width: w,
height: m,
url: j(t, { x: h, y: g, w, h: m })
});
}
return d;
}, O = async (t, e) => {
const c = await T(t), i = R(c, e), r = document.createElement("canvas"), n = r.getContext("2d");
if (!n)
throw new Error("Error initializing canvas context");
const o = c.tiles[0].width, a = c.tiles[0].height || c.tiles[0].width, l = (Math.ceil(e.w / o) + 1) * o, s = (Math.ceil(e.h / a) + 1) * a;
r.width = l, r.height = s;
const d = E({ callsPerSecond: 20 });
await Promise.all(i.map(async (w) => {
const m = await d.loadImage(w.url), u = w.x * o - e.x, f = w.y * a - e.y;
n.drawImage(m, u, f);
}));
const g = document.createElement("canvas");
g.width = e.w, g.height = e.h;
const h = g.getContext("2d");
if (!h)
throw new Error("Error initializing canvas context");
return h.drawImage(
r,
0,
0,
e.w,
e.h,
0,
0,
e.w,
e.h
), new Promise((w, m) => {
g.toBlob(
(u) => {
u ? w(u) : m(new Error("Failed to create blob"));
},
"image/jpeg",
0.95
);
});
}, I = (t, e) => {
const c = t.tiles[0].scaleFactors.sort((o, a) => a - o);
if (!e)
return c[0];
const i = e.width ? t.width / e.width : 1 / 0, r = e.height ? t.height / e.height : 1 / 0, n = Math.min(i, r);
for (const o of c)
if (o <= n)
return o;
return c[c.length - 1];
}, b = (t, e) => {
const c = I(t, e);
let i = Math.ceil(t.width / c), r = Math.ceil(t.height / c);
if (e) {
const n = t.width / t.height;
e.width && i < e.width && (i = e.width, r = Math.ceil(i / n)), e.height && r < e.height && (r = e.height, i = Math.ceil(r * n));
}
return { width: i, height: r };
}, k = (t, e) => {
const c = I(t, e), i = t.tiles[0].width, r = t.tiles[0].height || t.tiles[0].width, n = Math.ceil(t.width / (i * c)), o = Math.ceil(t.height / (r * c)), a = [];
for (let l = 0; l < o; l++)
for (let s = 0; s < n; s++) {
const d = Math.min(
i,
(t.width - s * i * c) / c
), g = Math.min(
r,
(t.height - l * r * c) / c
);
d <= 0 || g <= 0 || a.push({
url: `${t.id}/${s * i * c},${l * r * c},${d * c},${g * c}/${Math.ceil(d)},/0/default.jpg`,
width: Math.ceil(d),
height: Math.ceil(g),
x: s * i,
y: l * r
});
}
return a;
}, X = async (t, e) => {
const c = await T(t), i = k(c, e), r = b(c, e), n = document.createElement("canvas");
n.width = r.width, n.height = r.height;
const o = n.getContext("2d");
if (!o)
throw new Error("Error creating canvas context");
const a = E();
return await Promise.all(i.map(async (l) => {
const s = await a.loadImage(l.url);
o.drawImage(s, l.x, l.y);
})), new Promise((l, s) => {
n.toBlob((d) => {
d ? l(d) : s(new Error("Failed to create blob"));
}, "image/jpeg", 0.85);
});
};
export {
O as cropRegion,
X as getThumbnail
};