File size: 1,992 Bytes
7e3630c 412f992 7e3630c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 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<T extends "pixels" | "png" = "pixels">(options: {
src: Parameters<typeof Jimp.read>[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<PngData | PixelData | undefined>(
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 };
}
|