import { type Jimp } from "jimp"; import { useEffect, useState } from "react"; import { useImageCache } from "../InkPictureProvider.js"; import type { PixelData, PngData } from "../renderers/types.js"; import { fetchImage, getPngBuffer, getRawPixels } from "../utils/image.js"; export function useImage(options: { src: Parameters[0]; pixelWidth: number; pixelHeight: number; mode?: T; }): T extends "png" ? { imageData: PngData | undefined; error: boolean } : { imageData: PixelData | undefined; error: boolean } { const { src, pixelWidth, pixelHeight, mode = "pixels" } = options; const [imageData, setImageData] = useState( undefined, ); const [error, setError] = useState(false); const cache = useImageCache(); useEffect(() => { if (pixelWidth === 0 || pixelHeight === 0) return; let cancelled = false; const load = async () => { let image = typeof src === "string" ? cache?.get(src) : undefined; if (!image) { image = await fetchImage(src); if (cancelled) return; if (!image) { setError(true); setImageData(undefined); return; } if (typeof src === "string") { cache?.set(src, image); } } setError(false); image.cover({ w: pixelWidth, h: pixelHeight }); if (mode === "png") { const result = await getPngBuffer(image); if (!cancelled) { setImageData(result); } } else { const result = await getRawPixels(image); if (!cancelled) { setImageData(result); } } }; load(); return () => { cancelled = true; }; }, [src, pixelWidth, pixelHeight, mode, cache]); return { imageData, error } as T extends "png" ? { imageData: PngData | undefined; error: boolean } : { imageData: PixelData | undefined; error: boolean }; }