charify 1.0.0

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/README.md ADDED
@@ -0,0 +1,149 @@
1
+ ![charify logo](./assets/charify.svg)
2
+
3
+ High-quality image to ASCII art converter for the command line.
4
+ npm-ready. No dependencies on Unix tools.
5
+
6
+ ---
7
+
8
+ ## Install
9
+
10
+ Global install:
11
+
12
+ ```bash
13
+ npm install -g charify
14
+ ```
15
+
16
+ Run without installing:
17
+
18
+ ```bash
19
+ npx charify image.png
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Usage
25
+
26
+ ```bash
27
+ charify image.png
28
+ charify image.jpg -w 120
29
+ charify image.png -o output.txt
30
+ charify image.png --html -o output.html
31
+ charify --link https://example.com/image.jpg
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Options
37
+
38
+ | Option | Description |
39
+ | ------------ | ---------------------------------------------------------- |
40
+ | -w, --width | Output width (default: 100) |
41
+ | --ratio | Height/width ratio (default: 0.55) |
42
+ | --gamma | Gamma correction (default: 2.2) |
43
+ | --invert | Invert brightness |
44
+ | --html | Export as HTML (only works if output file ends with .html) |
45
+ | -o, --output | Output file (.txt or .html) |
46
+ | --link | Load image from URL |
47
+ | --charset | Custom ASCII charset |
48
+ | --preset | Use a preset: dense, light, blocks, minimal |
49
+
50
+ ---
51
+
52
+ ## Presets
53
+
54
+ | Name | Description |
55
+ | ------- | ---------------------- |
56
+ | dense | Best quality (default) |
57
+ | light | Softer output |
58
+ | blocks | Block-style ASCII |
59
+ | minimal | Very simple |
60
+
61
+ Example:
62
+
63
+ ```bash
64
+ charify image.png --preset blocks
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Custom Charset
70
+
71
+ Specify your own charset to control ASCII output characters:
72
+
73
+ ```bash
74
+ charify image.png --charset " .:-=+*#%@"
75
+ ```
76
+
77
+ ---
78
+
79
+ ## HTML Export
80
+
81
+ To export ASCII art wrapped in an HTML page, use `--html` **with** an output file ending in `.html`:
82
+
83
+ ```bash
84
+ charify image.png --html -o art.html
85
+ ```
86
+
87
+ If you use `--html` without specifying an output file ending with `.html`, it will be ignored and plain ASCII will be output instead.
88
+
89
+ ---
90
+
91
+ ## Input from URL
92
+
93
+ Load image from the internet:
94
+
95
+ ```bash
96
+ charify --link https://example.com/image.jpg
97
+ ```
98
+
99
+ You can combine with other options like `--html` and `-o`:
100
+
101
+ ```bash
102
+ charify --link https://example.com/image.jpg --html -o output.html
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Quality Tuning
108
+
109
+ Adjust gamma correction and character aspect ratio:
110
+
111
+ ```bash
112
+ charify image.png --gamma 2.0 --ratio 0.6
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Invert Brightness
118
+
119
+ Invert the brightness mapping:
120
+
121
+ ```bash
122
+ charify image.png --invert
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Local Development
128
+
129
+ Run directly without installing:
130
+
131
+ ```bash
132
+ node bin/charify.js image.png
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Donate
138
+
139
+ If you find **charify** useful and want to support development, you can donate any amount here:
140
+
141
+ [![Donate](https://img.shields.io/badge/Donate-00457C?logo=paypal)](https://paypal.me/Abdoelsayd81)
142
+
143
+ Thank you for your support!
144
+
145
+ ---
146
+
147
+ ## License
148
+
149
+ MIT
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg width="100%" height="100%" viewBox="0 0 512 127" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
4
+ <g transform="matrix(1,0,0,1,0,-6.755875)">
5
+ <g transform="matrix(1,-0,-0,1,-0,6.755875)">
6
+ <use xlink:href="#_Image1" x="0" y="0" width="512px" height="127px"/>
7
+ </g>
8
+ </g>
9
+ <defs>
10
+ <image id="_Image1" width="512px" height="127px" xlink:href="data:image/png;base64,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"/>
11
+ </defs>
12
+ </svg>
package/bin/charify.js ADDED
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import https from "https";
6
+ import sharp from "sharp";
7
+ import { Command } from "commander";
8
+
9
+ /* ================= CONFIG ================= */
10
+
11
+ const PRESETS = {
12
+ dense: "█▓▒░@%#*+=-:. ",
13
+ light: "#*+=-:. ",
14
+ blocks: "█▓▒░ ",
15
+ minimal: "#.+ ",
16
+ };
17
+
18
+ const DEFAULT_PRESET = "dense";
19
+ const DEFAULT_WIDTH = 100;
20
+ const DEFAULT_RATIO = 0.55;
21
+ const DEFAULT_GAMMA = 2.2;
22
+
23
+ /* ================= CLI ================= */
24
+
25
+ const program = new Command();
26
+
27
+ program
28
+ .name("charify")
29
+ .description("Convert images to ASCII art")
30
+ .argument("[image]", "local image path")
31
+ .option("--link <url>", "image URL")
32
+ .option("-w, --width <number>", "output width", String(DEFAULT_WIDTH))
33
+ .option("--ratio <number>", "height/width ratio", String(DEFAULT_RATIO))
34
+ .option("--gamma <number>", "gamma correction", String(DEFAULT_GAMMA))
35
+ .option("--charset <chars>", "custom ASCII charset")
36
+ .option("--preset <name>", "preset: dense | light | blocks | minimal")
37
+ .option("--invert", "invert brightness")
38
+ .option(
39
+ "--html",
40
+ "export as HTML (only works if output file ends with .html)"
41
+ )
42
+ .option("-o, --output <file>", "output file (.txt or .html)");
43
+ program
44
+ .addHelpText(
45
+ "before",
46
+ `
47
+ _ _ __
48
+ ___| |__ __ _ _ __(_)/ _|_ _
49
+ / __| '_ \\ / _' | '__| | |_| | | |
50
+ | (__| | | | (_| | | | | _| |_| |
51
+ \\___|_| |_|\\__,_|_| |_|_| \\__, |
52
+ |___/
53
+ `
54
+ )
55
+ .parse(process.argv);
56
+
57
+ const opts = program.opts();
58
+ const inputPath = program.args[0];
59
+
60
+ if (!opts.link && !inputPath) {
61
+ console.error("❌ Provide an image path or --link URL");
62
+ process.exit(1);
63
+ }
64
+
65
+ /* ================= HELPERS ================= */
66
+
67
+ function fetchImage(url) {
68
+ return new Promise((resolve, reject) => {
69
+ https.get(url, (res) => {
70
+ const chunks = [];
71
+ res.on("data", (d) => chunks.push(d));
72
+ res.on("end", () => resolve(Buffer.concat(chunks)));
73
+ res.on("error", reject);
74
+ });
75
+ });
76
+ }
77
+
78
+ function gammaCorrect(v, gamma) {
79
+ return Math.pow(v / 255, 1 / gamma) * 255;
80
+ }
81
+
82
+ function normalizeBuffer(buffer) {
83
+ let min = 255,
84
+ max = 0;
85
+ for (const v of buffer) {
86
+ if (v < min) min = v;
87
+ if (v > max) max = v;
88
+ }
89
+ if (max === min) return buffer;
90
+
91
+ return Buffer.from(
92
+ buffer.map((v) => Math.round(((v - min) / (max - min)) * 255))
93
+ );
94
+ }
95
+
96
+ function toAscii(buffer, width, charset, invert, gamma) {
97
+ let out = "";
98
+ const len = charset.length - 1;
99
+
100
+ for (let i = 0; i < buffer.length; i += width) {
101
+ for (let x = 0; x < width; x++) {
102
+ let v = buffer[i + x];
103
+ v = gammaCorrect(v, gamma);
104
+ const idx = Math.floor((v / 255) * len);
105
+ out += invert ? charset[len - idx] : charset[idx];
106
+ }
107
+ out += "\n";
108
+ }
109
+ return out;
110
+ }
111
+
112
+ function wrapHtml(ascii) {
113
+ return `<!doctype html>
114
+ <html>
115
+ <head>
116
+ <meta charset="utf-8">
117
+ <title>charify</title>
118
+ <style>
119
+ body {
120
+ background: #000;
121
+ color: #0f0;
122
+ font-family: monospace;
123
+ white-space: pre;
124
+ line-height: 1;
125
+ }
126
+ </style>
127
+ </head>
128
+ <body>${ascii}</body>
129
+ </html>`;
130
+ }
131
+
132
+ /* ================= MAIN ================= */
133
+
134
+ (async () => {
135
+ try {
136
+ const width = Number(opts.width);
137
+ const ratio = Number(opts.ratio);
138
+ const gamma = Number(opts.gamma);
139
+
140
+ const charset =
141
+ opts.charset || PRESETS[opts.preset] || PRESETS[DEFAULT_PRESET];
142
+
143
+ const inputBuffer = opts.link
144
+ ? await fetchImage(opts.link)
145
+ : fs.readFileSync(path.resolve(inputPath));
146
+
147
+ let sharpInstance = sharp(inputBuffer)
148
+ .resize({
149
+ width,
150
+ fit: sharp.fit.inside,
151
+ withoutEnlargement: true,
152
+ })
153
+ .grayscale();
154
+
155
+ const metadata = await sharpInstance.metadata();
156
+
157
+ const adjustedHeight = Math.round(metadata.height * ratio);
158
+
159
+ sharpInstance = sharpInstance.resize(width, adjustedHeight);
160
+
161
+ const { data, info } = await sharpInstance
162
+ .raw()
163
+ .toBuffer({ resolveWithObject: true });
164
+
165
+ const normalizedData = normalizeBuffer(data);
166
+
167
+ const ascii = toAscii(
168
+ normalizedData,
169
+ info.width,
170
+ charset,
171
+ opts.invert,
172
+ gamma
173
+ );
174
+
175
+ let output = ascii;
176
+ const wantHtml =
177
+ opts.html && opts.output && opts.output.toLowerCase().endsWith(".html");
178
+
179
+ if (wantHtml) {
180
+ output = wrapHtml(ascii);
181
+ } else if (
182
+ opts.html &&
183
+ (!opts.output || !opts.output.toLowerCase().endsWith(".html"))
184
+ ) {
185
+ if (!opts.output) {
186
+ output = ascii;
187
+ } else {
188
+ console.warn(
189
+ "⚠ Warning: --html ignored because output file extension is not .html"
190
+ );
191
+ output = ascii;
192
+ }
193
+ }
194
+
195
+ if (opts.output) {
196
+ fs.writeFileSync(opts.output, output, "utf8");
197
+ console.log("✔ Saved:", opts.output);
198
+ } else {
199
+ process.stdout.write(output);
200
+ }
201
+ } catch (err) {
202
+ console.error("❌ Error:", err.message);
203
+ process.exit(1);
204
+ }
205
+ })();
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "charify",
3
+ "version": "1.0.0",
4
+ "description": "High-quality image to ASCII art CLI",
5
+ "keywords": [
6
+ "ascii",
7
+ "ascii",
8
+ "art"
9
+ ],
10
+ "homepage": "https://github.com/abdodev/charify#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/abdodev/charify/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/abdodev/charify.git"
17
+ },
18
+ "license": "MIT",
19
+ "author": "AbdoDev",
20
+ "type": "module",
21
+ "main": "/bin/charify.js",
22
+ "bin": {
23
+ "charify": "bin/charify.js"
24
+ },
25
+ "scripts": {
26
+ "test": "echo \"Error: no test specified\" && exit 1"
27
+ },
28
+ "dependencies": {
29
+ "commander": "^12.0.0",
30
+ "sharp": "^0.33.0"
31
+ },
32
+ "devDependencies": {},
33
+ "engines": {
34
+ "node": ">=18"
35
+ }
36
+ }