From 493efdba013077520295730255d3b76266c9e3b6 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Tue, 26 May 2026 01:12:01 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=81=20Add=20new=20image=20information?= =?UTF-8?q?=20directory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- image-imformation/show-image.ts | 109 ++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100755 image-imformation/show-image.ts diff --git a/image-imformation/show-image.ts b/image-imformation/show-image.ts new file mode 100755 index 0000000..d5486f6 --- /dev/null +++ b/image-imformation/show-image.ts @@ -0,0 +1,109 @@ +#!/usr/bin/env runts -- --runtime-bun + +import {parseArgs} from "util"; + +const SUPPORTED_FORMATS = [".heic", ".jpeg", ".jpg", ".png", ".webp", ".gif", ".bmp", ".avif", ".tiff", ".tif"]; + +function printUsage() { + console.log(`Usage: bun run show-image.ts [image2] ... + +Display detailed information about image files. + +Arguments: + ... Input image file(s) + +Options: + --help Show this help message + +Supported formats: + ${SUPPORTED_FORMATS.join(", ")} + +Examples: + bun run show-image.ts photo.jpg + bun run show-image.ts a.jpg b.heic c.png`); +} + +function formatBytes(bytes: number): string { + if (bytes < 1024) return `${bytes} B`; + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; + return `${(bytes / (1024 * 1024)).toFixed(2)} MB`; +} + +function getFormat(ext: string): string { + switch (ext) { + case ".jpg": + case ".jpeg": + return "JPEG"; + case ".tif": + case ".tiff": + return "TIFF"; + default: + return ext.slice(1).toUpperCase(); + } +} + +async function showImage(path: string) { + const file = Bun.file(path); + + if (!(await file.exists())) { + console.error(`File not found: ${path}`); + return false; + } + + const ext = "." + file.name?.split(".").pop()?.toLowerCase(); + if (!SUPPORTED_FORMATS.includes(ext)) { + console.error(`Unsupported format: ${ext} (${path})`); + return false; + } + + const image = file.image(); + const meta = await image.metadata(); + const size = file.size; + + console.log(`File: ${path}`); + console.log(`Format: ${getFormat(ext)}`); + console.log(`Size: ${formatBytes(size)} (${size.toLocaleString()} bytes)`); + console.log(`Dimensions: ${meta.width} x ${meta.height}`); + console.log(`Aspect ratio: ${(meta.width / meta.height).toFixed(2)}`); + console.log(`Megapixels: ${((meta.width * meta.height) / 1_000_000).toFixed(2)} MP`); + console.log(); + return true; +} + +async function main() { + const args = Bun.argv.slice(2); + + if (args.length === 0 || args.includes("--help")) { + printUsage(); + process.exit(0); + } + + const {positionals} = parseArgs({args, allowPositionals: true, strict: false}); + + if (positionals.length === 0) { + console.error("Error: No input files specified.\n"); + printUsage(); + process.exit(1); + } + + let successCount = 0; + for (const path of positionals) { + const ok = await showImage(path); + if (ok) successCount++; + } + + if (positionals.length > 1) { + console.log(`Total: ${successCount}/${positionals.length} file(s) processed.`); + } + + if (successCount === 0) { + process.exit(1); + } +} + +main().catch((err) => { + console.error(err); +}); + +// @SCRIPT-SIGNATURE-V1: yk-r1.ES256.20260526T004141+08:00.MEQCIBjY8Rshew3TyWpojRAp +// /WewTldgEjhANbtyjw8Sn2VBAiARxfPLnmHlfkXZlVnN0lJoQmg1sqMmqouiHEjcxWQf3Q==