Download packages/coding-agent/src/utils/image-resize.ts from SaylorTwift/pi: direct link, hf CLI and curl.
- Browser
- Download file 3.9 kB
-
https://huggingface.co/SaylorTwift/pi/resolve/main/packages/coding-agent/src/utils/image-resize.ts
- Command line
-
hf download hf://SaylorTwift/pi/packages/coding-agent/src/utils/image-resize.ts
-
curl -L -o image-resize.ts https://huggingface.co/SaylorTwift/pi/resolve/main/packages/coding-agent/src/utils/image-resize.ts
3.9 kB
| import { Worker } from "node:worker_threads"; | |
| import { type ImageResizeOptions, type ResizedImage, resizeImageInProcess } from "./image-resize-core.ts"; | |
| export type { ImageResizeOptions, ResizedImage } from "./image-resize-core.ts"; | |
| interface ResizeImageWorkerResponse { | |
| result?: ResizedImage | null; | |
| error?: string; | |
| } | |
| function toTransferableBytes(input: Uint8Array): Uint8Array<ArrayBuffer> { | |
| // Transfer detaches the buffer, so transfer a worker-owned copy and leave the | |
| // caller's bytes intact. | |
| return new Uint8Array(input); | |
| } | |
| function isResizeImageWorkerResponse(value: unknown): value is ResizeImageWorkerResponse { | |
| return value !== null && typeof value === "object"; | |
| } | |
| function createResizeWorker(workerSpecifier: string | URL): Worker { | |
| return new Worker(workerSpecifier); | |
| } | |
| async function resizeImageInWorker( | |
| workerSpecifier: string | URL, | |
| inputBytes: Uint8Array, | |
| mimeType: string, | |
| options?: ImageResizeOptions, | |
| ): Promise<ResizedImage | null> { | |
| const worker = createResizeWorker(workerSpecifier); | |
| try { | |
| const inputBytesForWorker = toTransferableBytes(inputBytes); | |
| return await new Promise<ResizedImage | null>((resolve, reject) => { | |
| let settled = false; | |
| const settle = (result: ResizedImage | null): void => { | |
| if (settled) return; | |
| settled = true; | |
| resolve(result); | |
| }; | |
| const fail = (error: Error): void => { | |
| if (settled) return; | |
| settled = true; | |
| reject(error); | |
| }; | |
| worker.once("message", (message: unknown) => { | |
| if (!isResizeImageWorkerResponse(message)) { | |
| fail(new Error("Invalid image resize worker response")); | |
| return; | |
| } | |
| if (message.error) { | |
| fail(new Error(message.error)); | |
| return; | |
| } | |
| settle(message.result ?? null); | |
| }); | |
| worker.once("error", fail); | |
| worker.once("exit", (code) => { | |
| if (!settled) { | |
| fail(new Error(`Image resize worker exited with code ${code}`)); | |
| } | |
| }); | |
| worker.postMessage( | |
| { | |
| inputBytes: inputBytesForWorker, | |
| mimeType, | |
| options, | |
| }, | |
| [inputBytesForWorker.buffer], | |
| ); | |
| }); | |
| } finally { | |
| void worker.terminate().catch(() => undefined); | |
| } | |
| } | |
| /** | |
| * Resize an image to fit within the specified max dimensions and encoded file size. | |
| * Runs Photon in a worker thread so WASM decoding, resizing, and encoding do not | |
| * block the TUI event loop. If the worker cannot be loaded (for example in some | |
| * Bun compiled executable layouts), fall back to in-process resizing so image | |
| * reads still work. | |
| */ | |
| export async function resizeImage( | |
| inputBytes: Uint8Array, | |
| mimeType: string, | |
| options?: ImageResizeOptions, | |
| ): Promise<ResizedImage | null> { | |
| const isTypeScriptRuntime = import.meta.url.endsWith(".ts"); | |
| const workerUrl = new URL( | |
| isTypeScriptRuntime ? "./image-resize-worker.ts" : "./image-resize-worker.js", | |
| import.meta.url, | |
| ); | |
| // Bun compiled executables resolve worker entrypoints by string path, not via | |
| // new URL(..., import.meta.url). Try the string path first under Bun so the | |
| // release binary uses the embedded worker instead of falling back in-process. | |
| if (typeof process.versions.bun === "string") { | |
| try { | |
| return await resizeImageInWorker("./src/utils/image-resize-worker.ts", inputBytes, mimeType, options); | |
| } catch {} | |
| } | |
| try { | |
| return await resizeImageInWorker(workerUrl, inputBytes, mimeType, options); | |
| } catch { | |
| return resizeImageInProcess(inputBytes, mimeType, options); | |
| } | |
| } | |
| /** | |
| * Format a dimension note for resized images. | |
| * This helps the model understand the coordinate mapping. | |
| */ | |
| export function formatDimensionNote(result: ResizedImage): string | undefined { | |
| if (!result.wasResized) { | |
| return undefined; | |
| } | |
| const scale = result.originalWidth / result.width; | |
| return `[Image: original ${result.originalWidth}x${result.originalHeight}, displayed at ${result.width}x${result.height}. Multiply coordinates by ${scale.toFixed(2)} to map to original image.]`; | |
| } | |