generated from tpl/obsidian-sample-plugin
			Add in-browser image compression
This commit is contained in:
		
							parent
							
								
									05daa707d8
								
							
						
					
					
						commit
						2ba8523a24
					
				
							
								
								
									
										28
									
								
								src/main.ts
								
								
								
								
							
							
						
						
									
										28
									
								
								src/main.ts
								
								
								
								
							| 
						 | 
				
			
			@ -33,6 +33,7 @@ import { ReloadReadingLogCommand } from "@commands/ReloadReadingLogCommand";
 | 
			
		|||
import { registerReadingCalendarCodeBlockProcessor } from "@ui/code-blocks/ReadingCalendarCodeBlock";
 | 
			
		||||
import { registerAToZChallengeCodeBlockProcessor } from "@ui/code-blocks/AToZChallengeCodeBlock";
 | 
			
		||||
import moment from "@external/moment";
 | 
			
		||||
import { compressImage } from "@utils/image";
 | 
			
		||||
 | 
			
		||||
export default class BookTrackerPlugin extends Plugin {
 | 
			
		||||
	public settings: BookTrackerPluginSettings;
 | 
			
		||||
| 
						 | 
				
			
			@ -127,23 +128,28 @@ export default class BookTrackerPlugin extends Plugin {
 | 
			
		|||
		}
 | 
			
		||||
		filePath += fileName + "." + extension;
 | 
			
		||||
 | 
			
		||||
		const existingFile = this.app.vault.getFileByPath(filePath);
 | 
			
		||||
		if (existingFile) {
 | 
			
		||||
		let file = this.app.vault.getFileByPath(filePath);
 | 
			
		||||
		if (file) {
 | 
			
		||||
			if (this.settings.overwriteExistingCovers || overwrite) {
 | 
			
		||||
				await this.app.vault.modifyBinary(
 | 
			
		||||
					existingFile,
 | 
			
		||||
					response.arrayBuffer
 | 
			
		||||
				);
 | 
			
		||||
				await this.app.vault.modifyBinary(file, response.arrayBuffer);
 | 
			
		||||
			} else {
 | 
			
		||||
				new Notice("Cover image already exists: " + filePath);
 | 
			
		||||
				return file;
 | 
			
		||||
			}
 | 
			
		||||
			return existingFile;
 | 
			
		||||
		} else {
 | 
			
		||||
			file = await this.app.vault.createBinary(
 | 
			
		||||
				filePath,
 | 
			
		||||
				response.arrayBuffer
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return await this.app.vault.createBinary(
 | 
			
		||||
			filePath,
 | 
			
		||||
			response.arrayBuffer
 | 
			
		||||
		);
 | 
			
		||||
		await compressImage(this.app, file, {
 | 
			
		||||
			height: 400,
 | 
			
		||||
			quality: 0.8,
 | 
			
		||||
			maintainAspectRatio: true,
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		return file;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async createEntry(book: Book): Promise<void> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
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());
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue