perf: add cache for images

This commit is contained in:
2026-10-11 04:30:05 +05:00
parent b7613e8c0f
commit 5f4c3833a1
6 changed files with 32 additions and 9 deletions
@@ -1,5 +1,5 @@
<script lang="ts">
import { toDataUrl } from "$lib/core/io";
import { cachedDataUrl } from "$lib/core/io";
import type { ToolImageFile } from "$lib/registry";
interface Props {
@@ -8,7 +8,7 @@
let { files }: Props = $props();
const parts = $derived(
files.map((file) => ({ name: file.name, url: toDataUrl(file.image) })),
files.map((file) => ({ name: file.name, url: cachedDataUrl(file.image) })),
);
</script>
@@ -1,5 +1,5 @@
<script lang="ts">
import { toDataUrl } from "$lib/core/io";
import { cachedDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types";
import { t } from "$lib/i18n/t";
import type { FileResult, ResultKind, ResultNote } from "$lib/registry";
@@ -41,7 +41,7 @@
}: Props = $props();
const shown = $derived(maskOn && mask ? mask : result);
const resultUrl = $derived(shown ? toDataUrl(shown) : null);
const resultUrl = $derived(shown ? cachedDataUrl(shown) : null);
const resultDims = $derived(
resultKind === "image" && result
? `${result.width} × ${result.height}`
@@ -1,5 +1,5 @@
<script lang="ts">
import { toDataUrl } from "$lib/core/io";
import { cachedDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types";
import { t } from "$lib/i18n/t";
import type { InputMode, ToolImageFile } from "$lib/registry";
@@ -33,7 +33,7 @@
onuploadmany,
}: Props = $props();
const sourceUrl = $derived(source ? toDataUrl(source) : null);
const sourceUrl = $derived(source ? cachedDataUrl(source) : null);
const sourceDims = $derived(
source
? `${source.width} × ${source.height}` +
@@ -5,7 +5,7 @@
import { Star } from "@lucide/svelte";
import { DragDropProvider } from "@dnd-kit/svelte";
import { debounce } from "$lib/core/debounce";
import { toDataUrl } from "$lib/core/io";
import { cachedDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types";
import {
chainStepTitle,
@@ -301,7 +301,7 @@
{#if inSet.length > 1}
<PartsGrid files={inSet} />
{:else if input}
<img src={toDataUrl(input)} alt="" />
<img src={cachedDataUrl(input)} alt="" />
{:else}
<span class="empty">{t("resultCard.noResult")}</span>
{/if}
@@ -344,7 +344,7 @@
<PartsGrid files={outSet} />
{:else if out}
<img
src={toDataUrl(
src={cachedDataUrl(
masks.maskOn[i] && masks.masks[i]
? (masks.masks[i] as PixelImage)
: out,
+15
View File
@@ -82,6 +82,21 @@ export function toBase64(img: PixelImage): string {
return toDataUrl(img).slice("data:image/png;base64,".length);
}
const dataUrlCache = new WeakMap<PixelImage, string>();
// Display helper: PNG-encode on the main thread is expensive and templates
// re-render often with the same image (layout branch swaps, toggles). Results
// are treated as immutable -- a re-run produces new objects -- so an
// identity-keyed cache cannot go stale.
export function cachedDataUrl(img: PixelImage): string {
let url = dataUrlCache.get(img);
if (url === undefined) {
url = toDataUrl(img);
dataUrlCache.set(img, url);
}
return url;
}
export async function decodeTextImage(text: string): Promise<PixelImage> {
const cleaned = text.trim().replace(/^data:[^,]*,/, "");
if (cleaned.length === 0) {