canvas-image-toolkit 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,415 @@
1
+ # Image Filters Package
2
+
3
+ A lightweight JavaScript library for applying various image filters and effects to canvas images. This package provides simple functions for image manipulation including blur, grayscale, inversion, vintage effects, ASCII art generation, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install canvas-image-toolkit
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - 🎨 Multiple image filters (blur, grayscale, inversion, vintage)
14
+ - 🔤 ASCII art generation with color support
15
+ - 🖼️ Image data encoding/decoding utilities
16
+ - 🚀 Easy to use with HTML5 Canvas
17
+ - ⚡ In-place pixel manipulation for performance
18
+
19
+ ## Usage
20
+
21
+ ### Setup
22
+
23
+ First, import the functions you need:
24
+
25
+ ```javascript
26
+ import {
27
+ bLur,
28
+ BW,
29
+ ASCII_generator,
30
+ inversion,
31
+ vintage,
32
+ ImageDataGenerate,
33
+ encodeImageData,
34
+ decodeImageData
35
+ } from 'canvas-image-toolkit';
36
+ ```
37
+
38
+ ### Basic Example
39
+
40
+ ```javascript
41
+ // Setup canvas
42
+ const canvas = document.getElementById('myCanvas');
43
+ const ctx = canvas.getContext('2d');
44
+
45
+ // Load an image
46
+ const fileInput = document.getElementById('fileInput');
47
+ fileInput.addEventListener('change', async (e) => {
48
+ const file = e.target.files[0];
49
+
50
+ // Generate image data
51
+ const { width, height } = await ImageDataGenerate(file, canvas, ctx);
52
+
53
+ // Get pixel data
54
+ const imageData = ctx.getImageData(0, 0, width, height);
55
+ const pixels = imageData.data;
56
+
57
+ // Apply a filter
58
+ BW(pixels);
59
+
60
+ // Put modified pixels back to canvas
61
+ ctx.putImageData(imageData, 0, 0);
62
+ });
63
+ ```
64
+
65
+ ## API Reference
66
+
67
+ ### `bLur(pixels)`
68
+
69
+ Applies a blur effect to the image using a 21x21 box blur kernel.
70
+
71
+ **Parameters:**
72
+ - `pixels` (Uint8ClampedArray): The pixel data from canvas ImageData
73
+
74
+ **Example:**
75
+ ```javascript
76
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
77
+ bLur(imageData.data);
78
+ ctx.putImageData(imageData, 0, 0);
79
+ ```
80
+
81
+ ---
82
+
83
+ ### `BW(pixels)`
84
+
85
+ Converts the image to grayscale using average method.
86
+
87
+ **Parameters:**
88
+ - `pixels` (Uint8ClampedArray): The pixel data from canvas ImageData
89
+
90
+ **Example:**
91
+ ```javascript
92
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
93
+ BW(imageData.data);
94
+ ctx.putImageData(imageData, 0, 0);
95
+ ```
96
+
97
+ ---
98
+
99
+ ### `inversion(pixels)`
100
+
101
+ Inverts all colors in the image (negative effect).
102
+
103
+ **Parameters:**
104
+ - `pixels` (Uint8ClampedArray): The pixel data from canvas ImageData
105
+
106
+ **Example:**
107
+ ```javascript
108
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
109
+ inversion(imageData.data);
110
+ ctx.putImageData(imageData, 0, 0);
111
+ ```
112
+
113
+ ---
114
+
115
+ ### `vintage(pixels)`
116
+
117
+ Applies a vintage/sepia tone effect to the image.
118
+
119
+ **Parameters:**
120
+ - `pixels` (Uint8ClampedArray): The pixel data from canvas ImageData
121
+
122
+ **Example:**
123
+ ```javascript
124
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
125
+ vintage(imageData.data);
126
+ ctx.putImageData(imageData, 0, 0);
127
+ ```
128
+
129
+ ---
130
+
131
+ ### `ASCII_generator(pixels, width, options)`
132
+
133
+ Converts an image to ASCII art.
134
+
135
+ **Parameters:**
136
+ - `pixels` (Uint8ClampedArray): The pixel data from canvas ImageData
137
+ - `width` (number): Width of the image
138
+ - `options` (object): Optional configuration
139
+ - `char` (array): Custom ASCII characters (default: `[".", ",", ":", "-", "=", "+", "*", "#", "%", "@"]`)
140
+ - `color` (boolean): Whether to use colored output (default: `true`)
141
+
142
+ **Returns:** String containing HTML with ASCII art
143
+
144
+ **Example:**
145
+ ```javascript
146
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
147
+
148
+ // Basic usage with colors
149
+ const asciiArt = ASCII_generator(imageData.data, canvas.width);
150
+ document.getElementById('output').innerHTML = `<pre>${asciiArt}</pre>`;
151
+
152
+ // Custom characters without color
153
+ const customAscii = ASCII_generator(imageData.data, canvas.width, {
154
+ char: [' ', '.', ':', '-', '=', '+', '*', '#', '@'],
155
+ color: false
156
+ });
157
+ document.getElementById('output').innerHTML = `<pre>${customAscii}</pre>`;
158
+ ```
159
+
160
+ ---
161
+
162
+ ### `ImageDataGenerate(file, canvas, ctx)`
163
+
164
+ Loads an image file and draws it to a canvas.
165
+
166
+ **Parameters:**
167
+ - `file` (File): Image file from input element
168
+ - `canvas` (HTMLCanvasElement): Canvas element
169
+ - `ctx` (CanvasRenderingContext2D): Canvas 2D context
170
+
171
+ **Returns:** Promise resolving to `{width, height}`
172
+
173
+ **Example:**
174
+ ```javascript
175
+ const fileInput = document.getElementById('fileInput');
176
+ const canvas = document.getElementById('canvas');
177
+ const ctx = canvas.getContext('2d');
178
+
179
+ fileInput.addEventListener('change', async (e) => {
180
+ const file = e.target.files[0];
181
+ const { width, height } = await ImageDataGenerate(file, canvas, ctx);
182
+ console.log(`Image loaded: ${width}x${height}`);
183
+ });
184
+ ```
185
+
186
+ ---
187
+
188
+ ### `encodeImageData(imageData, width, height)`
189
+
190
+ Converts ImageData to a 2D array format for easier manipulation.
191
+
192
+ **Parameters:**
193
+ - `imageData` (Uint8ClampedArray): Pixel data
194
+ - `width` (number): Image width
195
+ - `height` (number): Image height
196
+
197
+ **Returns:** 2D array where each element is `[r, g, b, alpha]`
198
+
199
+ **Example:**
200
+ ```javascript
201
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
202
+ const binaryMatrix = encodeImageData(
203
+ imageData.data,
204
+ canvas.width,
205
+ canvas.height
206
+ );
207
+
208
+ // Now you can easily access pixels
209
+ const pixelColor = binaryMatrix[10][20]; // [r, g, b, alpha] at position (20, 10)
210
+ console.log(`Red: ${pixelColor[0]}, Green: ${pixelColor[1]}, Blue: ${pixelColor[2]}`);
211
+
212
+ // Manipulate specific pixels
213
+ binaryMatrix[10][20] = [255, 0, 0, 255]; // Set pixel to red
214
+
215
+ // You can also iterate through pixels easily
216
+ for (let y = 0; y < binaryMatrix.length; y++) {
217
+ for (let x = 0; x < binaryMatrix[y].length; x++) {
218
+ const [r, g, b, alpha] = binaryMatrix[y][x];
219
+ // Do something with each pixel
220
+ }
221
+ }
222
+ ```
223
+
224
+ ---
225
+
226
+ ### `decodeImageData(binary)`
227
+
228
+ Converts a 2D array format back to ImageData format.
229
+
230
+ **Parameters:**
231
+ - `binary` (array): 2D array where each element is `[r, g, b, alpha]`
232
+
233
+ **Returns:** Object with `{data, width, height}`
234
+
235
+ **Example:**
236
+ ```javascript
237
+ // Create a 2D array (e.g., 100x100 red image)
238
+ const binary = Array(100).fill(0).map(() =>
239
+ Array(100).fill(0).map(() => [255, 0, 0, 255])
240
+ );
241
+
242
+ // Convert to ImageData format
243
+ const { data, width, height } = decodeImageData(binary);
244
+
245
+ // Create ImageData and draw to canvas
246
+ const imageData = new ImageData(data, width, height);
247
+ ctx.putImageData(imageData, 0, 0);
248
+ ```
249
+
250
+ **Advanced Example - Encode, Modify, and Decode:**
251
+ ```javascript
252
+ // Step 1: Load and encode image
253
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
254
+ const binary = encodeImageData(imageData.data, canvas.width, canvas.height);
255
+
256
+ // Step 2: Manipulate the 2D array
257
+ // Example: Draw a red diagonal line
258
+ for (let i = 0; i < Math.min(binary.length, binary[0].length); i++) {
259
+ binary[i][i] = [255, 0, 0, 255]; // Red pixel
260
+ }
261
+
262
+ // Example: Create a blue square in the center
263
+ const centerY = Math.floor(binary.length / 2);
264
+ const centerX = Math.floor(binary[0].length / 2);
265
+ for (let y = centerY - 25; y < centerY + 25; y++) {
266
+ for (let x = centerX - 25; x < centerX + 25; x++) {
267
+ if (y >= 0 && y < binary.length && x >= 0 && x < binary[0].length) {
268
+ binary[y][x] = [0, 0, 255, 255]; // Blue pixel
269
+ }
270
+ }
271
+ }
272
+
273
+ // Step 3: Decode back to ImageData
274
+ const { data, width, height } = decodeImageData(binary);
275
+ const newImageData = new ImageData(data, width, height);
276
+
277
+ // Step 4: Draw to canvas
278
+ ctx.putImageData(newImageData, 0, 0);
279
+ ```
280
+
281
+ **Practical Use Case - Custom Filter:**
282
+ ```javascript
283
+ // Apply a custom filter using encode/decode
284
+ function applyCustomFilter() {
285
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
286
+ const binary = encodeImageData(imageData.data, canvas.width, canvas.height);
287
+
288
+ // Custom filter: Increase red channel by 50
289
+ for (let y = 0; y < binary.length; y++) {
290
+ for (let x = 0; x < binary[y].length; x++) {
291
+ binary[y][x][0] = Math.min(255, binary[y][x][0] + 50);
292
+ }
293
+ }
294
+
295
+ // Decode and display
296
+ const { data, width, height } = decodeImageData(binary);
297
+ const newImageData = new ImageData(data, width, height);
298
+ ctx.putImageData(newImageData, 0, 0);
299
+ }
300
+ ```
301
+
302
+ ## Complete Example
303
+
304
+ ```html
305
+ <!DOCTYPE html>
306
+ <html>
307
+ <head>
308
+ <title>Image Filters Demo</title>
309
+ <style>
310
+ canvas { border: 1px solid #ccc; }
311
+ pre { font-family: monospace; line-height: 0.8; font-size: 8px; }
312
+ </style>
313
+ </head>
314
+ <body>
315
+ <input type="file" id="fileInput" accept="image/*">
316
+ <div>
317
+ <button onclick="applyGrayscale()">Grayscale</button>
318
+ <button onclick="applyInvert()">Invert</button>
319
+ <button onclick="applyVintage()">Vintage</button>
320
+ <button onclick="applyBlur()">Blur</button>
321
+ <button onclick="generateASCII()">ASCII Art</button>
322
+ </div>
323
+ <canvas id="canvas"></canvas>
324
+ <div id="ascii-output"></div>
325
+
326
+ <script type="module">
327
+ import {
328
+ bLur, BW, ASCII_generator, inversion, vintage, ImageDataGenerate
329
+ } from 'image-filter-toolkit';
330
+
331
+ const canvas = document.getElementById('canvas');
332
+ const ctx = canvas.getContext('2d');
333
+ let originalImageData;
334
+
335
+ document.getElementById('fileInput').addEventListener('change', async (e) => {
336
+ const file = e.target.files[0];
337
+ await ImageDataGenerate(file, canvas, ctx);
338
+ originalImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
339
+ });
340
+
341
+ window.applyGrayscale = () => {
342
+ const imageData = new ImageData(
343
+ new Uint8ClampedArray(originalImageData.data),
344
+ originalImageData.width,
345
+ originalImageData.height
346
+ );
347
+ BW(imageData.data);
348
+ ctx.putImageData(imageData, 0, 0);
349
+ };
350
+
351
+ window.applyInvert = () => {
352
+ const imageData = new ImageData(
353
+ new Uint8ClampedArray(originalImageData.data),
354
+ originalImageData.width,
355
+ originalImageData.height
356
+ );
357
+ inversion(imageData.data);
358
+ ctx.putImageData(imageData, 0, 0);
359
+ };
360
+
361
+ window.applyVintage = () => {
362
+ const imageData = new ImageData(
363
+ new Uint8ClampedArray(originalImageData.data),
364
+ originalImageData.width,
365
+ originalImageData.height
366
+ );
367
+ vintage(imageData.data);
368
+ ctx.putImageData(imageData, 0, 0);
369
+ };
370
+
371
+ window.applyBlur = () => {
372
+ const imageData = new ImageData(
373
+ new Uint8ClampedArray(originalImageData.data),
374
+ originalImageData.width,
375
+ originalImageData.height
376
+ );
377
+ bLur(imageData.data);
378
+ ctx.putImageData(imageData, 0, 0);
379
+ };
380
+
381
+ window.generateASCII = () => {
382
+ const ascii = ASCII_generator(
383
+ originalImageData.data,
384
+ originalImageData.width,
385
+ { color: true }
386
+ );
387
+ document.getElementById('ascii-output').innerHTML = `<pre>${ascii}</pre>`;
388
+ };
389
+ </script>
390
+ </body>
391
+ </html>
392
+ ```
393
+
394
+ ## Browser Compatibility
395
+
396
+ This package works in all modern browsers that support:
397
+ - HTML5 Canvas
398
+ - ES6 Modules
399
+ - Uint8ClampedArray
400
+
401
+ ## License
402
+
403
+ MIT
404
+
405
+ ## Contributing
406
+
407
+ Contributions are welcome! Please feel free to submit a Pull Request.
408
+
409
+ ## Author
410
+
411
+ Neeraj Dhyani
412
+
413
+ ## Repository
414
+
415
+ [https://github.com/Neeraj-Dhyani/NPM_Project_image_binary_tool](https://github.com/Neeraj-Dhyani/NPM_Project_image_binary_tool)
package/decoder.js ADDED
@@ -0,0 +1,24 @@
1
+
2
+ export function decodeImageData(binary){
3
+ const height = binary.length
4
+ const width = binary[0].length
5
+ const imageData = new Uint8ClampedArray(width*height*4)
6
+ for(let y=0; y; y++){
7
+ if (binary[y].length !== width) {
8
+ throw new Error("Invalid binary matrix: inconsistent row width");
9
+ }
10
+ for(let x=0; x<SIZE; x++){
11
+ const i = (y*width+x)*4
12
+ const [r, g, b, alpha] = binary[y][x]
13
+ imageData[i] = r
14
+ imageData[i+1] = g
15
+ imageData[i+2] = b
16
+ imageData[i+3] = alpha
17
+ }
18
+ }
19
+ return({
20
+ data:imageData,
21
+ width,
22
+ height
23
+ })
24
+ }
package/encoder.js ADDED
@@ -0,0 +1,22 @@
1
+ export function encodeImageData(imageData, width, height){
2
+ const Binary = []
3
+ for(let y=0; y<height; y++){
4
+ let row = []
5
+ for(let x =0; x<width; x++){
6
+ const i = (y * SIZE + x) * 4;
7
+ const r = imageData[i];
8
+ const g = imageData[i + 1];
9
+ const b = imageData[i + 2];
10
+ const alpha = data[i+3]
11
+ if(alpha<50){
12
+ row.push([0,0,0,0]);
13
+ }else{
14
+ row.push([r,g,b,alpha])
15
+ }
16
+
17
+ }
18
+ Binary.push(row)
19
+ }
20
+ return Binary
21
+
22
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Convert image pixels to grayscale (in-place)
3
+ * @param {Uint8ClampedArray} pixels
4
+ */
5
+ export function BW(pixels){
6
+ for(let i=0; i<=pixels.height; i+=4){
7
+ let r = pixels[i]
8
+ let g = pixels[i+1]
9
+ let b = pixels[i+2]
10
+
11
+ let average = (r+g+b)/3
12
+
13
+ pixels[i] = average
14
+ pixels[i+1] = average
15
+ pixels[i+2] = average
16
+
17
+ }
18
+ }
package/filter/blur.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Convert image pixels to grayscale (in-place)
3
+ * @param {Uint8ClampedArray} pixels
4
+ */
5
+ export function bLur(pixels){
6
+ let copy = new Uint8ClampedArray(pixels)
7
+ for(let y = 1; y<=canvas.height; y++){
8
+ for(let x = 1; x<=canvas.width; x++){
9
+ let r = 0, g = 0, b = 0;
10
+ let count = 0
11
+ for(let ky = -10; ky<=10; ky++){
12
+ for(let kx = -10; kx<=10; kx++){
13
+ let py = y + ky
14
+ let px = x + kx
15
+ let index = (py * canvas.width + px) * 4
16
+ r += copy[index]
17
+ g += copy[index+1]
18
+ b += copy[index+2]
19
+ count += 1
20
+ }
21
+ }
22
+ let i = (y * canvas.width + x)*4
23
+ pixels[i] = r/count
24
+ pixels[i+1] = g/count
25
+ pixels[i+2] = b/count
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Convert image pixels to grayscale (in-place)
3
+ * @param {Uint8ClampedArray} pixels
4
+ */
5
+ export function ASCII_generator(pixels, width, option={}){
6
+ const ASCII_CHARS = option.char||["." , ",", ":", "-", "=", "+","*","#","%", "@"]
7
+ const color = option.color??true
8
+ let asciiHTML = ''
9
+ const height = Math.floor(pixels.length / 4 / width);
10
+ for(let y = 0; y<height; y++){
11
+ for(x =0; x<width; x++){
12
+ let i = (y*width+x)*4
13
+ const r = imageData[i]
14
+ const g = imageData[i+1]
15
+ const b = imageData[i+2]
16
+
17
+ const brightness = 0.299 * r + 0.587 * g + 0.114 * b;
18
+
19
+ const charIndex = Math.floor(
20
+ (brightness / 255) * (ASCII_CHARS.length - 1)
21
+ );
22
+
23
+ const char = ASCII_CHARS[charIndex]
24
+ if(color){
25
+ asciiHTML += `<span style="color:rgb(${r}, ${g}, ${b})">${char}</span>`
26
+ }else{
27
+ asciiHTML += char
28
+ }
29
+
30
+ }
31
+ asciiHTML+='\n'
32
+ }
33
+ return asciiHTML
34
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Convert image pixels to grayscale (in-place)
3
+ * @param {Uint8ClampedArray} pixels
4
+ */
5
+ export function inversion(pixels){
6
+ for (let i = pixels.length - 4; i >= 0; i -= 4) {
7
+ let r = pixels[i];
8
+ let g = pixels[i + 1];
9
+ let b = pixels[i + 2];
10
+
11
+ pixels[i] = 255- r ;
12
+ pixels[i + 1] = 255- g;
13
+ pixels[i + 2] = 255- b ;
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Convert image pixels to grayscale (in-place)
3
+ * @param {Uint8ClampedArray} pixels
4
+ */
5
+ export function vintage(pixels){
6
+
7
+ for(let i=0; i<pixels.length; i++){
8
+ let r = pixels[i]
9
+ let g = pixels[i+1]
10
+ let b = pixels[i+2]
11
+
12
+ pixels[i] = (0.393 * r) + (0.769 * g) + (0.189 * b);
13
+ pixels[i + 1] = (0.349 * r) + (0.686 * g) + (0.168 * b);
14
+ pixels[i + 2] = (0.272 * r) + (0.534 * g) + (0.131 * b);
15
+
16
+ }
17
+
18
+ }
@@ -0,0 +1,21 @@
1
+ export function ImageDataGenerate (file, canvas, ctx){
2
+ return new Promise((resolve)=>{
3
+ const image_icon = new Image()
4
+
5
+ image_icon.onload = ()=>{
6
+ SIZE = image_icon.width
7
+ canvas.width = image_icon.width;
8
+ canvas.height = image_icon.height;
9
+ ctx.fillStyle = "white"
10
+ ctx.clearRect(0, 0, SIZE, SIZE)
11
+ ctx.drawImage(image_icon, 0, 0, SIZE, SIZE)
12
+ resolve({
13
+ width:image_icon.width,
14
+ height:image_icon.height
15
+ })
16
+
17
+ }
18
+ image_icon.src = URL.createObjectURL(file)
19
+ })
20
+
21
+ }
package/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export {BW} from "./filter/blackandwhite"
2
+ export {bLur} from "./filter/blur"
3
+ export {ASCII_generator} from "./filter/generate_ASCII"
4
+ export {inversion} from "./filter/inversion"
5
+ export {vintage} from "./filter/vintage"
6
+ export {encodeImageData} from "./encoder"
7
+ export {decodeImageData} from "./decoder"
8
+ export {ImageDataGenerate} from "./genImageData"
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "canvas-image-toolkit",
3
+ "version": "1.0.0",
4
+ "description": "Image encode/decode, filters, ASCII generator using raw ImageData",
5
+ "keywords": [
6
+ "image",
7
+ "binary",
8
+ "ascii",
9
+ "canvas"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Neeraj Dhyani",
13
+ "type": "module",
14
+ "exports": {
15
+ ".": "./index.js"
16
+ },
17
+ "main": "index.js",
18
+ "scripts": {
19
+ "test": "echo \\\"No tests specified\\\"\""
20
+ }
21
+ }