mirror of https://github.com/VERT-sh/VERT.git
fix: rest of imagemagick formats
fixed over 35 formats in past few commits because i did a stupid (setting bit depth to "auto" apparently breaks 30 formats, but not all). also clamp sizes for certain formats
This commit is contained in:
parent
058f16af61
commit
125854414c
|
|
@ -234,7 +234,7 @@ export class MagickConverter extends Converter {
|
||||||
default: "auto",
|
default: "auto",
|
||||||
options: [
|
options: [
|
||||||
{ value: "auto", label: "Auto" },
|
{ value: "auto", label: "Auto" },
|
||||||
{ value: "custom", label: "Custom" },
|
// { value: "custom", label: "Custom" },
|
||||||
{ value: "8", label: "8-bit" },
|
{ value: "8", label: "8-bit" },
|
||||||
{ value: "16", label: "16-bit" },
|
{ value: "16", label: "16-bit" },
|
||||||
{ value: "32", label: "32-bit" },
|
{ value: "32", label: "32-bit" },
|
||||||
|
|
|
||||||
|
|
@ -339,83 +339,95 @@ const magickConvert = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmt === "ICO" && !singleSize) {
|
const icons = ["ICO", "ICON", "CUR"]; // TODO: icns (1024x1024 max)
|
||||||
const standardSizes = [16, 24, 32, 48, 64, 128, 256, 512];
|
if (icons.includes(fmt)) {
|
||||||
|
if (singleSize) {
|
||||||
let desired = 0;
|
// clamp to 256x256
|
||||||
if (resolution && resolution !== "auto") {
|
clampRes(img, 256);
|
||||||
const actualResolution =
|
|
||||||
resolution === "custom"
|
|
||||||
? (conversionSettings.customResolution as string)
|
|
||||||
: resolution;
|
|
||||||
const [wsel, hsel] = (actualResolution || "")
|
|
||||||
.split("x")
|
|
||||||
.map((d: string) => parseInt(d) || 0);
|
|
||||||
desired = Math.max(wsel || 0, hsel || 0);
|
|
||||||
} else {
|
} else {
|
||||||
desired = Math.max(img.width || 0, img.height || 0);
|
// generate all standard sizes for icons
|
||||||
}
|
const standardSizes = [16, 24, 32, 48, 64, 128, 256];
|
||||||
|
|
||||||
if (desired <= 0) desired = Math.max(...standardSizes);
|
let desired = 0;
|
||||||
if (desired > Math.max(...standardSizes))
|
if (resolution && resolution !== "auto") {
|
||||||
desired = Math.max(...standardSizes);
|
const actualResolution =
|
||||||
|
resolution === "custom"
|
||||||
|
? (conversionSettings.customResolution as string)
|
||||||
|
: resolution;
|
||||||
|
const [wsel, hsel] = (actualResolution || "")
|
||||||
|
.split("x")
|
||||||
|
.map((d: string) => parseInt(d) || 0);
|
||||||
|
desired = Math.max(wsel || 0, hsel || 0);
|
||||||
|
} else {
|
||||||
|
desired = Math.max(img.width || 0, img.height || 0);
|
||||||
|
}
|
||||||
|
|
||||||
const sizes = standardSizes.filter((s) => s <= desired);
|
if (desired <= 0) desired = Math.max(...standardSizes);
|
||||||
if (sizes.length === 0) sizes.push(Math.min(...standardSizes));
|
if (desired > Math.max(...standardSizes))
|
||||||
|
desired = Math.max(...standardSizes);
|
||||||
|
|
||||||
const sourcePng = await new Promise<Uint8Array>((resolve) => {
|
const sizes = standardSizes.filter((s) => s <= desired);
|
||||||
img.write(MagickFormat.Png, (o: Uint8Array) =>
|
if (sizes.length === 0) sizes.push(Math.min(...standardSizes));
|
||||||
resolve(structuredClone(o)),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`encoding sizes for ico: ${sizes.join(", ")}`);
|
const sourcePng = await new Promise<Uint8Array>((resolve) => {
|
||||||
|
img.write(MagickFormat.Png, (o: Uint8Array) =>
|
||||||
return await new Promise<Uint8Array>((resolve) => {
|
resolve(structuredClone(o)),
|
||||||
MagickImageCollection.use((collection) => {
|
|
||||||
for (const size of sizes) {
|
|
||||||
const variant = MagickImage.create(
|
|
||||||
sourcePng,
|
|
||||||
new MagickReadSettings({ format: MagickFormat.Png }),
|
|
||||||
);
|
|
||||||
|
|
||||||
const scale =
|
|
||||||
size / Math.max(variant.width, variant.height);
|
|
||||||
const newW = Math.max(1, Math.round(variant.width * scale));
|
|
||||||
const newH = Math.max(
|
|
||||||
1,
|
|
||||||
Math.round(variant.height * scale),
|
|
||||||
);
|
|
||||||
variant.resize(newW, newH);
|
|
||||||
|
|
||||||
collection.push(variant);
|
|
||||||
console.log(
|
|
||||||
`added size ${size}x${size} to MagickImageCollection`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
collection.write(
|
|
||||||
fmt as unknown as MagickFormat,
|
|
||||||
(o: Uint8Array) => {
|
|
||||||
resolve(structuredClone(o));
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
console.log(`encoding sizes for ico: ${sizes.join(", ")}`);
|
||||||
|
|
||||||
|
return await new Promise<Uint8Array>((resolve) => {
|
||||||
|
MagickImageCollection.use((collection) => {
|
||||||
|
for (const size of sizes) {
|
||||||
|
const variant = MagickImage.create(
|
||||||
|
sourcePng,
|
||||||
|
new MagickReadSettings({
|
||||||
|
format: MagickFormat.Png,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const scale =
|
||||||
|
size / Math.max(variant.width, variant.height);
|
||||||
|
const newW = Math.max(
|
||||||
|
1,
|
||||||
|
Math.round(variant.width * scale),
|
||||||
|
);
|
||||||
|
const newH = Math.max(
|
||||||
|
1,
|
||||||
|
Math.round(variant.height * scale),
|
||||||
|
);
|
||||||
|
variant.resize(newW, newH);
|
||||||
|
|
||||||
|
collection.push(variant);
|
||||||
|
console.log(
|
||||||
|
`added size ${size}x${size} to MagickImageCollection`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.write(
|
||||||
|
fmt as unknown as MagickFormat,
|
||||||
|
(o: Uint8Array) => {
|
||||||
|
resolve(structuredClone(o));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (fmt === "RGF") clampRes(img, 254); // max 254x254
|
||||||
|
|
||||||
const result = await new Promise<Uint8Array>((resolve, reject) => {
|
const result = await new Promise<Uint8Array>((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
// quality, depth, colorSpace, transparency, metadata
|
// quality, depth, colorSpace, transparency, metadata
|
||||||
const quality = conversionSettings.quality as number;
|
const quality = conversionSettings.quality as number;
|
||||||
const bitDepth = conversionSettings.depth as number;
|
const bitDepth = conversionSettings.depth;
|
||||||
const colorSpace = conversionSettings.colorSpace as string;
|
const colorSpace = conversionSettings.colorSpace as string;
|
||||||
const transparency = conversionSettings.transparency as boolean;
|
const transparency = conversionSettings.transparency as boolean;
|
||||||
const metadata = conversionSettings.metadata as boolean;
|
const metadata = conversionSettings.metadata as boolean;
|
||||||
|
|
||||||
// magick-wasm automatically clamps (https://github.com/dlemstra/magick-wasm/blob/76fc6f2b0c0497d2ddc251bbf6174b4dc92ac3ea/src/magick-image.ts#L2480)
|
// magick-wasm automatically clamps (https://github.com/dlemstra/magick-wasm/blob/76fc6f2b0c0497d2ddc251bbf6174b4dc92ac3ea/src/magick-image.ts#L2480)
|
||||||
if (quality) img.quality = quality;
|
if (quality) img.quality = quality;
|
||||||
if (bitDepth) img.depth = bitDepth;
|
if (bitDepth !== "auto") img.depth = bitDepth;
|
||||||
if (!metadata) img.strip();
|
if (!metadata) img.strip();
|
||||||
if (colorSpace) {
|
if (colorSpace) {
|
||||||
switch (colorSpace) {
|
switch (colorSpace) {
|
||||||
|
|
@ -462,6 +474,19 @@ const magickConvert = async (
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clampRes = (img: IMagickImage, maxSize: number) => {
|
||||||
|
const w = img.width;
|
||||||
|
const h = img.height;
|
||||||
|
|
||||||
|
if (w > maxSize || h > maxSize) {
|
||||||
|
const scale = maxSize / Math.max(w, h);
|
||||||
|
const newW = Math.max(1, Math.round(w * scale));
|
||||||
|
const newH = Math.max(1, Math.round(h * scale));
|
||||||
|
|
||||||
|
img.resize(newW, newH);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onmessage = async (e) => {
|
onmessage = async (e) => {
|
||||||
const message = e.data;
|
const message = e.data;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue