@freqhole/reliquary 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worker/blob-worker-client.d.ts +5 -0
- package/dist/worker/blob-worker-client.d.ts.map +1 -1
- package/dist/worker/blob-worker-client.js +17 -0
- package/dist/worker/blob-worker-client.test.js +16 -0
- package/dist/worker/blob-worker-logic.d.ts +5 -0
- package/dist/worker/blob-worker-logic.d.ts.map +1 -1
- package/dist/worker/blob-worker-logic.js +20 -0
- package/dist/worker/blob-worker-logic.test.js +16 -0
- package/dist/worker/midden-worker-client.d.ts +4 -1
- package/dist/worker/midden-worker-client.d.ts.map +1 -1
- package/dist/worker/midden-worker-client.js +5 -0
- package/dist/worker/midden-worker-client.test.js +1 -0
- package/dist/worker/midden-worker-contract.d.ts +12 -0
- package/dist/worker/midden-worker-contract.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -94,6 +94,11 @@ export interface ResizeImageOptions {
|
|
|
94
94
|
maxHeight?: number;
|
|
95
95
|
quality?: number;
|
|
96
96
|
cropSquare?: boolean;
|
|
97
|
+
/** if true, fit the whole image inside a maxWidth x maxHeight square
|
|
98
|
+
* without cropping, padding the shorter axis with transparent pixels -
|
|
99
|
+
* the right choice for document/page thumbnails, where cropping can cut
|
|
100
|
+
* off real content. takes precedence over `cropSquare` when both are set. */
|
|
101
|
+
fitSquare?: boolean;
|
|
97
102
|
mime?: string;
|
|
98
103
|
}
|
|
99
104
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blob-worker-client.d.ts","sourceRoot":"","sources":["../../src/worker/blob-worker-client.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAsBtD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAuDnF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAOzC;AAiCD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAInE;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAeD;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAQxF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAC1E,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAkC3C;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,SAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOhG;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAQnE"}
|
|
1
|
+
{"version":3,"file":"blob-worker-client.d.ts","sourceRoot":"","sources":["../../src/worker/blob-worker-client.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAsBtD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAuDnF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAOzC;AAiCD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAInE;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAeD;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAQxF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAC1E,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAkC3C;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;iFAG6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,SAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOhG;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAQnE"}
|
|
@@ -314,10 +314,27 @@ async function mainThreadResizeImage(blob, options) {
|
|
|
314
314
|
const maxHeight = options?.maxHeight ?? 200;
|
|
315
315
|
const quality = options?.quality ?? 0.8;
|
|
316
316
|
const cropSquare = options?.cropSquare ?? false;
|
|
317
|
+
const fitSquare = options?.fitSquare ?? false;
|
|
317
318
|
const mime = options?.mime ?? "image/webp";
|
|
318
319
|
let bitmap = null;
|
|
319
320
|
try {
|
|
320
321
|
bitmap = await createImageBitmap(blob);
|
|
322
|
+
if (fitSquare) {
|
|
323
|
+
const scale = Math.min(maxWidth / bitmap.width, maxHeight / bitmap.height);
|
|
324
|
+
const drawW = Math.max(1, Math.round(bitmap.width * scale));
|
|
325
|
+
const drawH = Math.max(1, Math.round(bitmap.height * scale));
|
|
326
|
+
const dx = Math.floor((maxWidth - drawW) / 2);
|
|
327
|
+
const dy = Math.floor((maxHeight - drawH) / 2);
|
|
328
|
+
const canvas = new OffscreenCanvas(maxWidth, maxHeight);
|
|
329
|
+
const ctx = canvas.getContext("2d");
|
|
330
|
+
if (!ctx)
|
|
331
|
+
return null;
|
|
332
|
+
ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, dx, dy, drawW, drawH);
|
|
333
|
+
const out = await canvas.convertToBlob({ type: mime, quality });
|
|
334
|
+
const buf = await out.arrayBuffer();
|
|
335
|
+
const b64 = await fallbackBase64Encode(buf);
|
|
336
|
+
return `data:${mime};base64,${b64}`;
|
|
337
|
+
}
|
|
321
338
|
let sx = 0;
|
|
322
339
|
let sy = 0;
|
|
323
340
|
let sw = bitmap.width;
|
|
@@ -26,6 +26,7 @@ class FakeImageBitmap {
|
|
|
26
26
|
class FakeOffscreenCanvasContext {
|
|
27
27
|
drawImage = vi.fn();
|
|
28
28
|
}
|
|
29
|
+
let lastFakeCanvas;
|
|
29
30
|
class FakeOffscreenCanvas {
|
|
30
31
|
width;
|
|
31
32
|
height;
|
|
@@ -33,6 +34,7 @@ class FakeOffscreenCanvas {
|
|
|
33
34
|
constructor(width, height) {
|
|
34
35
|
this.width = width;
|
|
35
36
|
this.height = height;
|
|
37
|
+
lastFakeCanvas = this;
|
|
36
38
|
}
|
|
37
39
|
getContext() {
|
|
38
40
|
return this.context;
|
|
@@ -128,6 +130,20 @@ describe("resizeImageToWebpDataUrl", () => {
|
|
|
128
130
|
const result = await resizeImageToWebpDataUrl(new Blob(["x"], { type: "image/png" }));
|
|
129
131
|
expect(result).toBeNull();
|
|
130
132
|
});
|
|
133
|
+
it("centers a non-square bitmap without cropping when fitSquare is set", async () => {
|
|
134
|
+
installCanvasFakes({ width: 400, height: 100 });
|
|
135
|
+
const result = await resizeImageToWebpDataUrl(new Blob(["x"], { type: "image/png" }), {
|
|
136
|
+
maxWidth: 200,
|
|
137
|
+
maxHeight: 200,
|
|
138
|
+
fitSquare: true,
|
|
139
|
+
});
|
|
140
|
+
expect(result).toMatch(/^data:image\/webp;base64,/);
|
|
141
|
+
// 400x100 fit into 200x200 scales to 200x50, centered with 75px of
|
|
142
|
+
// padding above and below — the full source width is drawn (no crop).
|
|
143
|
+
expect(lastFakeCanvas?.width).toBe(200);
|
|
144
|
+
expect(lastFakeCanvas?.height).toBe(200);
|
|
145
|
+
expect(lastFakeCanvas?.context.drawImage).toHaveBeenCalledWith(expect.anything(), 0, 0, 400, 100, 0, 75, 200, 50);
|
|
146
|
+
});
|
|
131
147
|
});
|
|
132
148
|
describe("generateThumbnailDataUrl", () => {
|
|
133
149
|
it("skips non-image blobs", async () => {
|
|
@@ -67,6 +67,11 @@ export interface ResizeImageOptions {
|
|
|
67
67
|
quality?: number;
|
|
68
68
|
/** if true, center-crop to a square before resizing */
|
|
69
69
|
cropSquare?: boolean;
|
|
70
|
+
/** if true, fit the whole image inside a maxWidth x maxHeight square
|
|
71
|
+
* without cropping, padding the shorter axis with transparent pixels -
|
|
72
|
+
* the right choice for document/page thumbnails, where cropping can cut
|
|
73
|
+
* off real content. takes precedence over `cropSquare` when both are set. */
|
|
74
|
+
fitSquare?: boolean;
|
|
70
75
|
/** output mime type (default: "image/webp") */
|
|
71
76
|
mime?: string;
|
|
72
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blob-worker-logic.d.ts","sourceRoot":"","sources":["../../src/worker/blob-worker-logic.ts"],"names":[],"mappings":"AAqBA;oEACoE;AACpE,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D;;;qCAGqC;AACrC,eAAO,MAAM,QAAQ,oBAAoB,CAAC;AAE1C;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAYlE;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CASvE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAOnE;AAuBD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCtF;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAUlF;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CAcxB;AAID,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"blob-worker-logic.d.ts","sourceRoot":"","sources":["../../src/worker/blob-worker-logic.ts"],"names":[],"mappings":"AAqBA;oEACoE;AACpE,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D;;;qCAGqC;AACrC,eAAO,MAAM,QAAQ,oBAAoB,CAAC;AAE1C;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAYlE;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CASvE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAOnE;AAuBD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCtF;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAUlF;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CAcxB;AAID,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;iFAG6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6ExB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,SAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOhG;AAoBD;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAwBnD;AAED,+DAA+D;AAC/D,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CxF;AAED,uDAAuD;AACvD,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3D;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAOzD;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,MAAM,CAAC,CAOpE"}
|
|
@@ -176,10 +176,30 @@ export async function resizeImageToWebpDataUrl(blob, options) {
|
|
|
176
176
|
const maxHeight = options?.maxHeight ?? 200;
|
|
177
177
|
const quality = options?.quality ?? 0.8;
|
|
178
178
|
const cropSquare = options?.cropSquare ?? false;
|
|
179
|
+
const fitSquare = options?.fitSquare ?? false;
|
|
179
180
|
const mime = options?.mime ?? "image/webp";
|
|
180
181
|
let bitmap = null;
|
|
181
182
|
try {
|
|
182
183
|
bitmap = await createImageBitmap(blob);
|
|
184
|
+
if (fitSquare) {
|
|
185
|
+
const scale = Math.min(maxWidth / bitmap.width, maxHeight / bitmap.height);
|
|
186
|
+
const drawW = Math.max(1, Math.round(bitmap.width * scale));
|
|
187
|
+
const drawH = Math.max(1, Math.round(bitmap.height * scale));
|
|
188
|
+
const dx = Math.floor((maxWidth - drawW) / 2);
|
|
189
|
+
const dy = Math.floor((maxHeight - drawH) / 2);
|
|
190
|
+
const canvas = new OffscreenCanvas(maxWidth, maxHeight);
|
|
191
|
+
const ctx = canvas.getContext("2d");
|
|
192
|
+
if (!ctx)
|
|
193
|
+
return null;
|
|
194
|
+
// canvas starts fully transparent — draw the scaled image centered,
|
|
195
|
+
// leaving transparent padding on the shorter axis rather than
|
|
196
|
+
// cropping content off the longer one.
|
|
197
|
+
ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, dx, dy, drawW, drawH);
|
|
198
|
+
const out = await canvas.convertToBlob({ type: mime, quality });
|
|
199
|
+
const buf = await out.arrayBuffer();
|
|
200
|
+
const b64 = await base64Encode(buf);
|
|
201
|
+
return `data:${mime};base64,${b64}`;
|
|
202
|
+
}
|
|
183
203
|
let sx = 0;
|
|
184
204
|
let sy = 0;
|
|
185
205
|
let sw = bitmap.width;
|
|
@@ -63,6 +63,7 @@ class FakeImageBitmap {
|
|
|
63
63
|
class FakeOffscreenCanvasContext {
|
|
64
64
|
drawImage = vi.fn();
|
|
65
65
|
}
|
|
66
|
+
let lastFakeCanvas;
|
|
66
67
|
class FakeOffscreenCanvas {
|
|
67
68
|
width;
|
|
68
69
|
height;
|
|
@@ -70,6 +71,7 @@ class FakeOffscreenCanvas {
|
|
|
70
71
|
constructor(width, height) {
|
|
71
72
|
this.width = width;
|
|
72
73
|
this.height = height;
|
|
74
|
+
lastFakeCanvas = this;
|
|
73
75
|
}
|
|
74
76
|
getContext() {
|
|
75
77
|
return this.context;
|
|
@@ -176,6 +178,20 @@ describe("resizeImageToWebpDataUrl", () => {
|
|
|
176
178
|
const result = await resizeImageToWebpDataUrl(new Blob(["x"], { type: "image/png" }));
|
|
177
179
|
expect(result).toBeNull();
|
|
178
180
|
});
|
|
181
|
+
it("centers a non-square bitmap without cropping when fitSquare is set", async () => {
|
|
182
|
+
installCanvasFakes({ width: 400, height: 100 });
|
|
183
|
+
const result = await resizeImageToWebpDataUrl(new Blob(["x"], { type: "image/png" }), {
|
|
184
|
+
maxWidth: 200,
|
|
185
|
+
maxHeight: 200,
|
|
186
|
+
fitSquare: true,
|
|
187
|
+
});
|
|
188
|
+
expect(result).toMatch(/^data:image\/webp;base64,/);
|
|
189
|
+
// 400x100 fit into 200x200 scales to 200x50, centered with 75px of
|
|
190
|
+
// padding above and below — the full source width is drawn (no crop).
|
|
191
|
+
expect(lastFakeCanvas?.width).toBe(200);
|
|
192
|
+
expect(lastFakeCanvas?.height).toBe(200);
|
|
193
|
+
expect(lastFakeCanvas?.context.drawImage).toHaveBeenCalledWith(expect.anything(), 0, 0, 400, 100, 0, 75, 200, 50);
|
|
194
|
+
});
|
|
179
195
|
});
|
|
180
196
|
describe("generateThumbnailDataUrl", () => {
|
|
181
197
|
it("skips non-image blobs", async () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Comlink from "comlink";
|
|
2
|
-
import { type MiddenWorkerApi, type StreamInfo } from "./midden-worker-contract.js";
|
|
2
|
+
import { type MiddenWorkerApi, type StreamInfo, type WorkerActiveTransfer } from "./midden-worker-contract.js";
|
|
3
3
|
type Api = Comlink.Remote<MiddenWorkerApi>;
|
|
4
4
|
/** main-thread face of a worker-held BiStream. implements BiStreamLike. */
|
|
5
5
|
export declare class WorkerBiStream {
|
|
@@ -77,6 +77,9 @@ export declare class WorkerMiddenNode {
|
|
|
77
77
|
release_blob(blake3Hash: string): Promise<void>;
|
|
78
78
|
restrict_blob_to_peers(blake3Hash: string, peerNodeIds: string[]): Promise<void>;
|
|
79
79
|
clear_blob_restriction(blake3Hash: string): Promise<void>;
|
|
80
|
+
/** snapshot of this node's own outgoing blob transfers currently in
|
|
81
|
+
* flight - see `MiddenNode::get_active_transfers` in `midden/src/lib.rs`. */
|
|
82
|
+
get_active_transfers(): Promise<WorkerActiveTransfer[]>;
|
|
80
83
|
start_import(): WorkerImportSession;
|
|
81
84
|
ensure_blob(peerAddr: string, blake3Hash: string): Promise<boolean>;
|
|
82
85
|
download_verified_with_ensure(peerAddr: string, blake3Hash: string): Promise<Uint8Array>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midden-worker-client.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"midden-worker-client.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAC;AAKrC,KAAK,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AAa3C,2EAA2E;AAC3E,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,UAAU;IAGnC,YAAY,IAAI,MAAM;IAItB,IAAI,IAAI,MAAM;IAIR,YAAY,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI1C,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIjD,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,gEAAgE;IAChE,KAAK,IAAI,IAAI;CAKd;AAED;;cAEc;AACd,qBAAa,mBAAmB;IAGlB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;gBAEf,GAAG,EAAE,GAAG;IAI/B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAK/B,KAAK,IAAI,IAAI;CAGd;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,MAAM,CAAC;AAE9C;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO;IAOP;2BACuB;WACV,MAAM,CACjB,SAAS,EAAE,UAAU,GAAG,IAAI,EAC5B,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IAiD5B,6EAA6E;IAC7E,SAAS,IAAI,IAAI;IAMjB,OAAO,IAAI,MAAM;IAIjB,UAAU,IAAI,UAAU;IAMlB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAIhE,MAAM,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAQxC,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9C,0BAA0B,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,UAAU,CAAA;KAAE,CAAC;IAIxF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAI1E,mEAAmE;IACnE,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvD,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhF,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD;kFAC8E;IAC9E,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAIvD,YAAY,IAAI,mBAAmB;IAM7B,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAInE,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIxF,sCAAsC,CAC1C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACtC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC;IAUhB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAIxF,gCAAgC,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAS1B,uCAAuC,CAC3C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,EACpD,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACtC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAWlB;;;gEAG4D;IACtD,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3D,2DAA2D;IACrD,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,qEAAqE;IAC/D,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAMxE,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAG7C"}
|
|
@@ -199,6 +199,11 @@ export class WorkerMiddenNode {
|
|
|
199
199
|
clear_blob_restriction(blake3Hash) {
|
|
200
200
|
return this.api.clearBlobRestriction(blake3Hash);
|
|
201
201
|
}
|
|
202
|
+
/** snapshot of this node's own outgoing blob transfers currently in
|
|
203
|
+
* flight - see `MiddenNode::get_active_transfers` in `midden/src/lib.rs`. */
|
|
204
|
+
get_active_transfers() {
|
|
205
|
+
return this.api.getActiveTransfers();
|
|
206
|
+
}
|
|
202
207
|
start_import() {
|
|
203
208
|
return new WorkerImportSession(this.api);
|
|
204
209
|
}
|
|
@@ -30,6 +30,7 @@ function makeFakeApi(overrides = {}) {
|
|
|
30
30
|
releaseBlob: vi.fn(),
|
|
31
31
|
restrictBlobToPeers: vi.fn(),
|
|
32
32
|
clearBlobRestriction: vi.fn(),
|
|
33
|
+
getActiveTransfers: vi.fn(async () => []),
|
|
33
34
|
startImport: vi.fn(async () => 1),
|
|
34
35
|
importPush: vi.fn(async () => undefined),
|
|
35
36
|
importFinish: vi.fn(async () => "blake3-hex"),
|
|
@@ -11,6 +11,15 @@ export interface MiddenWorkerIdentity {
|
|
|
11
11
|
nodeId: string;
|
|
12
12
|
secretKey: Uint8Array;
|
|
13
13
|
}
|
|
14
|
+
/** one outgoing blob transfer in flight on the worker-hosted node - same
|
|
15
|
+
* shape as a raw wasm MiddenNode's `get_active_transfers()`
|
|
16
|
+
* (`{peerId, blake3, bytesSent, totalSize}`, see midden/src/transfers.rs). */
|
|
17
|
+
export interface WorkerActiveTransfer {
|
|
18
|
+
peerId: string;
|
|
19
|
+
blake3: string;
|
|
20
|
+
bytesSent: number;
|
|
21
|
+
totalSize: number;
|
|
22
|
+
}
|
|
14
23
|
/**
|
|
15
24
|
* the entry's comlink-exposed surface. every method here runs on the
|
|
16
25
|
* worker thread; callback arguments (`onProgress`, `onChunk`) arrive as
|
|
@@ -49,6 +58,9 @@ export interface MiddenWorkerApi {
|
|
|
49
58
|
releaseBlob(blake3Hash: string): Promise<void>;
|
|
50
59
|
restrictBlobToPeers(blake3Hash: string, peerNodeIds: string[]): Promise<void>;
|
|
51
60
|
clearBlobRestriction(blake3Hash: string): Promise<void>;
|
|
61
|
+
/** snapshot of this node's own outgoing blob transfers currently in
|
|
62
|
+
* flight - forwards to the wasm node's `get_active_transfers()`. */
|
|
63
|
+
getActiveTransfers(): Promise<WorkerActiveTransfer[]>;
|
|
52
64
|
startImport(): Promise<number>;
|
|
53
65
|
importPush(sessionId: number, chunk: Uint8Array): Promise<void>;
|
|
54
66
|
importFinish(sessionId: number): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midden-worker-contract.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-contract.ts"],"names":[],"mappings":"AAqBA;mEACmE;AACnE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;uEACuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAGlE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5D;2BACuB;IACvB,MAAM,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACrC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAChE,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACxE,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,wEAAwE;IACxE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG7C,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACrF,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD;;8BAE0B;IAC1B,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"midden-worker-contract.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-contract.ts"],"names":[],"mappings":"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"}
|