@kaviyarasan022/image-compressor-target 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ const yargs = require("yargs/yargs");
3
+ const { hideBin } = require("yargs/helpers");
4
+ const path = require("path");
5
+ const fs = require("fs");
6
+ const axios = require("axios");
7
+ const os = require("os");
8
+ const { compressToTarget } = require("../lib/compressor");
9
+
10
+ /**
11
+ * Download image from a URL to a temporary local file
12
+ * @param {string} url - direct image URL
13
+ * @returns {Promise<string>} - path to downloaded temp file
14
+ */
15
+ async function downloadImage(url) {
16
+ const tmpPath = path.join(os.tmpdir(), "img_compress_temp_" + Date.now() + path.extname(url.split("?")[0]));
17
+ const writer = fs.createWriteStream(tmpPath);
18
+ const response = await axios({
19
+ url,
20
+ method: "GET",
21
+ responseType: "stream",
22
+ });
23
+
24
+ response.data.pipe(writer);
25
+
26
+ return new Promise((resolve, reject) => {
27
+ writer.on("finish", () => resolve(tmpPath));
28
+ writer.on("error", reject);
29
+ });
30
+ }
31
+
32
+ (async () => {
33
+ const argv = yargs(hideBin(process.argv))
34
+ .usage("Usage: node bin/cli.js <input> --target 300kb --out output.jpg")
35
+ .demandCommand(1, "Please provide an image path or URL")
36
+ .option("target", {
37
+ alias: "t",
38
+ type: "string",
39
+ describe: "Target file size (e.g., 300kb, 1mb)",
40
+ demandOption: true,
41
+ })
42
+ .option("out", {
43
+ alias: "o",
44
+ type: "string",
45
+ describe: "Output file path (default: input_compressed.jpg)",
46
+ })
47
+ .help()
48
+ .argv;
49
+
50
+ let inputPath = argv._[0];
51
+ let tempDownloaded = false;
52
+
53
+ const isURL = /^https?:\/\//i.test(inputPath);
54
+ if (isURL) {
55
+ console.log("🌐 Downloading image from URL...");
56
+ inputPath = await downloadImage(inputPath);
57
+ tempDownloaded = true;
58
+ } else {
59
+ // Check local file exists
60
+ if (!fs.existsSync(inputPath)) {
61
+ console.error("❌ Input file not found:", inputPath);
62
+ process.exit(1);
63
+ }
64
+ }
65
+
66
+ const outputPath =
67
+ argv.out ||
68
+ path.join(
69
+ path.dirname(inputPath),
70
+ path.basename(inputPath, path.extname(inputPath)) + "_compressed" + path.extname(inputPath)
71
+ );
72
+
73
+ // ✅ Ensure output folder exists
74
+ const outputFolder = path.dirname(outputPath);
75
+ if (!fs.existsSync(outputFolder)) {
76
+ fs.mkdirSync(outputFolder, { recursive: true });
77
+ }
78
+
79
+ console.log(`🧠 Compressing ${inputPath} to around ${argv.target}...`);
80
+ try {
81
+ const result = await compressToTarget(inputPath, outputPath, argv.target);
82
+ console.log(`✅ Done! Final size: ${result.finalSizeKB} KB`);
83
+ console.log(`📁 Saved to: ${outputPath}`);
84
+ } catch (e) {
85
+ console.error("❌ Compression failed:", e.message);
86
+ } finally {
87
+ // Clean up temp file if downloaded
88
+ if (tempDownloaded && fs.existsSync(inputPath)) {
89
+ fs.unlinkSync(inputPath);
90
+ }
91
+ }
92
+ })();
@@ -0,0 +1,6 @@
1
+ const { compressToTarget } = require("../lib/compressor");
2
+
3
+ (async () => {
4
+ const result = await compressToTarget("./images/test.jpg", "./images/test_small.jpg", "300kb");
5
+ console.log(result);
6
+ })();
Binary file
package/index.js ADDED
@@ -0,0 +1,34 @@
1
+
2
+
3
+ const { compressToTarget } = require("./lib/compressor");
4
+
5
+ /**
6
+
7
+ *
8
+ * @param {string} inputPath - Path to input image file (jpg/png/webp)
9
+ * @param {string} outputPath - Path where compressed image will be saved
10
+ * @param {string|number} targetSize - e.g. "300kb", "1mb", or bytes number
11
+ * @returns {Promise<object>} - compression result info
12
+ *
13
+ * Example:
14
+ * const { compressToTarget } = require("image-compressor-target");
15
+ * await compressToTarget("photo.jpg", "photo_small.jpg", "300kb");
16
+ */
17
+ module.exports = { compressToTarget };
18
+
19
+ // If executed directly (like `node index.js`), show quick usage help
20
+ if (require.main === module) {
21
+ console.log(`
22
+ 🖼️ Image Compressor CLI
23
+ =============================
24
+ Usage:
25
+ node index.js <input> --target 300kb --out output.jpg
26
+
27
+ Or after linking:
28
+ img-compress ./photo.jpg --target 300kb --out photo_small.jpg
29
+
30
+ You can also import in JS:
31
+ const { compressToTarget } = require('image-compressor-target');
32
+ await compressToTarget('photo.jpg', 'photo_small.jpg', '300kb');
33
+ `);
34
+ }
@@ -0,0 +1,50 @@
1
+ const fs = require("fs").promises;
2
+ const sharp = require("sharp");
3
+
4
+ function parseSize(sizeStr) {
5
+ if (typeof sizeStr === "number") return sizeStr;
6
+
7
+ const s = String(sizeStr).trim().toLowerCase().replace(/\s+/g, "");
8
+ const match = s.match(/^(\d+(?:\.\d+)?)(b|kb|mb)?$/);
9
+ if (!match) throw new Error("Invalid size format. Use e.g. 300kb, 0.3mb, or 50000.");
10
+
11
+ const value = parseFloat(match[1]);
12
+ const unit = match[2] || "b";
13
+
14
+ if (unit === "b") return Math.round(value);
15
+ if (unit === "kb") return Math.round(value * 1024);
16
+ if (unit === "mb") return Math.round(value * 1024 * 1024);
17
+
18
+ return Math.round(value);
19
+ }
20
+
21
+ async function compressToTarget(inputPath, outputPath, targetSizeStr) {
22
+ const targetBytes = parseSize(targetSizeStr);
23
+ const inputBuffer = await fs.readFile(inputPath);
24
+ let quality = 90;
25
+ let buffer = inputBuffer;
26
+
27
+ for (let i = 0; i < 10; i++) {
28
+ const { data } = await sharp(buffer)
29
+ .jpeg({ quality })
30
+ .toBuffer({ resolveWithObject: true });
31
+
32
+ if (data.length <= targetBytes || quality < 30) {
33
+ await fs.writeFile(outputPath, data);
34
+ return {
35
+ success: true,
36
+ finalSizeKB: (data.length / 1024).toFixed(2),
37
+ quality,
38
+ };
39
+ }
40
+
41
+ quality -= 10;
42
+ buffer = data;
43
+ }
44
+
45
+ throw new Error(
46
+ "Could not reach target size. Try a larger target or smaller image."
47
+ );
48
+ }
49
+
50
+ module.exports = { compressToTarget };
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@kaviyarasan022/image-compressor-target",
3
+ "version": "1.0.1",
4
+ "description": "A Node.js CLI tool to compress images to a target size.",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "image-compressor": "./bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": ["image", "compressor", "cli", "tool", "image-optimization"],
13
+ "author": "Kaviyarasan M",
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "axios": "^1.12.2"
17
+ }
18
+ }