Gemma4-WebGPU / src /utils /image-utils.ts
BryanBradfo's picture
Gemma 4 multimodal WebGPU detection Space
576d07a
const MAX_DIMENSION = 384;
/**
* Resize an image to fit within MAX_DIMENSION while preserving aspect ratio.
* Returns a base64 data URL.
*/
export function resizeImage(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const img = new Image();
img.onload = () => {
let { width, height } = img;
if (width > MAX_DIMENSION || height > MAX_DIMENSION) {
const scale = MAX_DIMENSION / Math.max(width, height);
width = Math.round(width * scale);
height = Math.round(height * scale);
}
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d")!;
ctx.drawImage(img, 0, 0, width, height);
resolve(canvas.toDataURL("image/jpeg", 0.9));
};
img.onerror = reject;
img.src = reader.result as string;
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
/**
* Load an image URL, resize to MAX_DIMENSION, return as base64 data URL.
*/
export async function urlToDataUrl(url: string): Promise<string> {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status} for ${url}`);
const blob = await response.blob();
const file = new File([blob], "image.jpg", { type: blob.type });
return resizeImage(file);
}
/**
* Get image dimensions from a data URL.
*/
export function getImageDimensions(
dataUrl: string,
): Promise<{ width: number; height: number }> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve({ width: img.width, height: img.height });
img.onerror = reject;
img.src = dataUrl;
});
}