From 2b2c9146c2383706d2acf7190f01fb0a46b157da Mon Sep 17 00:00:00 2001 From: not-nullptr <62841684+not-nullptr@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:52:13 +0100 Subject: [PATCH] feat: .dng support --- bun.lock | 4 +-- package.json | 2 +- src/lib/converters/vips.svelte.ts | 1 + src/lib/workers/vips.ts | 52 +++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index 0ec2c3e..667bac1 100644 --- a/bun.lock +++ b/bun.lock @@ -10,7 +10,7 @@ "@fontsource/azeret-mono": "^5.1.1", "@fontsource/lexend": "^5.1.2", "@fontsource/radio-canada-big": "^5.1.1", - "@imagemagick/magick-wasm": "^0.0.32", + "@imagemagick/magick-wasm": "^0.0.34", "client-zip": "^2.4.6", "clsx": "^2.1.1", "lucide-svelte": "^0.475.0", @@ -132,7 +132,7 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="], - "@imagemagick/magick-wasm": ["@imagemagick/magick-wasm@0.0.32", "", {}, "sha512-+niNRuJk4ZPE9PDzBg19Kjyl+CEdAgaJBXQSFXmO1CTDoYOxrZ3DBdstfs1+8r77hjoiph+4Wu4qpldfcrKm7A=="], + "@imagemagick/magick-wasm": ["@imagemagick/magick-wasm@0.0.34", "", {}, "sha512-vSTe4cfR8U8r2Ityo6s3iRFVK903W4fhur3t/ixc6vLSAJXmqXC9cKXz2NkkDBUVU7ssJTYMiTKAb1S9RY+ZdQ=="], "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], diff --git a/package.json b/package.json index 4ca2138..efed84e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@fontsource/azeret-mono": "^5.1.1", "@fontsource/lexend": "^5.1.2", "@fontsource/radio-canada-big": "^5.1.1", - "@imagemagick/magick-wasm": "^0.0.32", + "@imagemagick/magick-wasm": "^0.0.34", "client-zip": "^2.4.6", "clsx": "^2.1.1", "lucide-svelte": "^0.475.0", diff --git a/src/lib/converters/vips.svelte.ts b/src/lib/converters/vips.svelte.ts index 663ec01..031d4b4 100644 --- a/src/lib/converters/vips.svelte.ts +++ b/src/lib/converters/vips.svelte.ts @@ -23,6 +23,7 @@ export class VipsConverter extends Converter { ".gif", ".hdr", ".jpe", + ".dng", ".mat", ".pbm", ".pfm", diff --git a/src/lib/workers/vips.ts b/src/lib/workers/vips.ts index cdfe5d5..42e6054 100644 --- a/src/lib/workers/vips.ts +++ b/src/lib/workers/vips.ts @@ -1,10 +1,24 @@ import Vips from "wasm-vips"; +import { + initializeImageMagick, + MagickFormat, + MagickImage, + MagickReadSettings, +} from "@imagemagick/magick-wasm"; +import wasm from "@imagemagick/magick-wasm/magick.wasm?url"; const vipsPromise = Vips({ dynamicLibraries: [], }); +const magickPromise = initializeImageMagick(new URL(wasm, import.meta.url)); + +const magickRequiredFormats = [".dng"]; +const unsupportedFrom: string[] = []; +const unsupportedTo = [".dng"]; + vipsPromise + .then(() => magickPromise) .then(() => { postMessage({ type: "loaded" }); }) @@ -18,7 +32,45 @@ const handleMessage = async (message: any): Promise => { switch (message.type) { case "convert": { if (!message.to.startsWith(".")) message.to = `.${message.to}`; + if (unsupportedFrom.includes(message.input.from)) { + return { + type: "error", + error: `Unsupported input format ${message.input.from}`, + }; + } + + if (unsupportedTo.includes(message.to)) { + return { + type: "error", + error: `Unsupported output format ${message.to}`, + }; + } + const buffer = await message.input.file.arrayBuffer(); + if ( + magickRequiredFormats.includes(message.input.from) || + magickRequiredFormats.includes(message.to) + ) { + const magick = MagickImage.create( + new Uint8Array(buffer), + new MagickReadSettings({ + format: message.input.from + .slice(1) + .toUpperCase() as MagickFormat, + }), + ); + + const dngBuffer = await new Promise((resolve) => + magick.write(message.to.slice(1).toUpperCase(), (data) => { + resolve(data); + }), + ); + + return { + type: "finished", + output: dngBuffer, + }; + } let image = vips.Image.newFromBuffer(buffer, ""); // check if animated image & keep it animated when converting