obsidian-book-tracker/src/utils/image.ts

73 lines
1.5 KiB
TypeScript

import { type App, type TFile } from "obsidian";
interface CompressOptions {
width?: number;
height?: number;
maintainAspectRatio?: boolean;
quality?: number;
}
export async function compressImage(
app: App,
file: TFile,
options: CompressOptions
) {
const img = await new Promise<HTMLImageElement>((resolve) => {
const img = new Image();
img.src = app.vault.getResourcePath(file);
img.onload = () => {
resolve(img);
};
});
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d")!;
const quality = options.quality ?? 1;
let height = options.height;
let width = options.width;
if (!width && !height) {
width = img.width;
height = img.height;
} else if (!width && height) {
width = height * (img.width / img.height);
} else if (!height && width) {
height = width * (img.height / img.width);
}
if (options.maintainAspectRatio) {
const aspectRatio = img.width / img.height;
if (options.height)
if (width! > height!) {
height = width! / aspectRatio;
} else {
width = height! * aspectRatio;
}
}
console.log(width, height);
canvas.width = width!;
canvas.height = height!;
ctx.drawImage(img, 0, 0, width!, height!);
const blob = await new Promise<Blob>((resolve, reject) => {
canvas.toBlob(
(blob) => {
if (blob) {
resolve(blob);
} else {
reject(new Error("Failed to compress image"));
}
},
"image/jpeg",
quality
);
});
return app.vault.modifyBinary(file, await blob.arrayBuffer());
}