sweetcorn 0.2.1 → 0.2.2
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/dist/custom-processors.d.ts +6 -0
- package/dist/custom-processors.js +25 -0
- package/dist/index.js +11 -18
- package/dist/processors.d.ts +1 -6
- package/dist/threshold-maps.json +27 -5
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ArrayOrBuffer } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A collection of pixel mutation processors that deviate from the standardized threshold map and
|
|
4
|
+
* error diffusion algorithms.
|
|
5
|
+
*/
|
|
6
|
+
export declare const customProcessors: Record<'white-noise' | 'threshold', (pixels: ArrayOrBuffer<number>) => void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A collection of pixel mutation processors that deviate from the standardized threshold map and
|
|
3
|
+
* error diffusion algorithms.
|
|
4
|
+
*/
|
|
5
|
+
export const customProcessors = {
|
|
6
|
+
/**
|
|
7
|
+
* White noise dithering (pretty rough and ugly)
|
|
8
|
+
*/
|
|
9
|
+
'white-noise'(pixels) {
|
|
10
|
+
for (let index = 0; index < pixels.length; index++) {
|
|
11
|
+
const pixelValue = pixels[index];
|
|
12
|
+
pixels[index] = pixelValue / 255 < Math.random() ? 0 : 255;
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
/**
|
|
16
|
+
* Basic quantization. This could be represented as a threshold map of `[[128]]` but defining it
|
|
17
|
+
* like this allows it to be implemented more efficiently.
|
|
18
|
+
*/
|
|
19
|
+
threshold(pixels) {
|
|
20
|
+
for (let index = 0; index < pixels.length; index++) {
|
|
21
|
+
const pixelValue = pixels[index];
|
|
22
|
+
pixels[index] = pixelValue < 128 ? 0 : 255;
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { customProcessors } from './custom-processors.js';
|
|
2
2
|
import diffusionKernels from './diffusion-kernels.js';
|
|
3
|
+
import { applyDiffusionKernel, applyThresholdMap } from './processors.js';
|
|
3
4
|
import thresholdMaps from './threshold-maps.json' with { type: 'json' };
|
|
4
5
|
let sharp;
|
|
5
6
|
async function loadSharp() {
|
|
@@ -21,6 +22,8 @@ async function loadSharp() {
|
|
|
21
22
|
* @returns A new Sharp image instance.
|
|
22
23
|
*/
|
|
23
24
|
export default async function sweetcorn(image, options) {
|
|
25
|
+
// Clone the input image to avoid mutating it.
|
|
26
|
+
image = image.clone();
|
|
24
27
|
const { algorithm } = options;
|
|
25
28
|
if (!sharp)
|
|
26
29
|
sharp = await loadSharp();
|
|
@@ -28,30 +31,20 @@ export default async function sweetcorn(image, options) {
|
|
|
28
31
|
// We use gamma to linearize the colorspace, and improve the perceptual quality.
|
|
29
32
|
image.gamma(2.2, 1).greyscale();
|
|
30
33
|
// Get raw pixel data for this image.
|
|
31
|
-
const
|
|
34
|
+
const { data: pixels, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
32
35
|
const thresholdMap = options.thresholdMap || thresholdMaps[algorithm];
|
|
33
36
|
const diffusionKernel = options.diffusionKernel || diffusionKernels[algorithm];
|
|
37
|
+
const customProcessor = customProcessors[algorithm];
|
|
34
38
|
if (thresholdMap) {
|
|
35
|
-
applyThresholdMap(
|
|
39
|
+
applyThresholdMap(pixels, info.width, thresholdMap);
|
|
36
40
|
}
|
|
37
41
|
else if (diffusionKernel) {
|
|
38
|
-
applyDiffusionKernel(
|
|
39
|
-
}
|
|
40
|
-
else if (algorithm === 'white-noise') {
|
|
41
|
-
// White noise dithering (pretty rough and ugly)
|
|
42
|
-
for (let index = 0; index < rawPixels.data.length; index++) {
|
|
43
|
-
const pixelValue = rawPixels.data[index];
|
|
44
|
-
rawPixels.data[index] = pixelValue / 255 < Math.random() ? 0 : 255;
|
|
45
|
-
}
|
|
42
|
+
applyDiffusionKernel(pixels, info.width, info.height, diffusionKernel);
|
|
46
43
|
}
|
|
47
|
-
else if (
|
|
48
|
-
|
|
49
|
-
for (let index = 0; index < rawPixels.data.length; index++) {
|
|
50
|
-
const pixelValue = rawPixels.data[index];
|
|
51
|
-
rawPixels.data[index] = pixelValue < 128 ? 0 : 255;
|
|
52
|
-
}
|
|
44
|
+
else if (customProcessor) {
|
|
45
|
+
customProcessor(pixels);
|
|
53
46
|
}
|
|
54
47
|
// Convert raw pixel data back into a Sharp image.
|
|
55
|
-
const outputImage = sharp(
|
|
48
|
+
const outputImage = sharp(pixels, { raw: info });
|
|
56
49
|
return outputImage;
|
|
57
50
|
}
|
package/dist/processors.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
interface ArrayOrBuffer<T> {
|
|
3
|
-
length: number;
|
|
4
|
-
[n: number]: T;
|
|
5
|
-
}
|
|
1
|
+
import { ArrayOrBuffer } from './types.js';
|
|
6
2
|
/** Applies a threshold map to raw pixel data for ordered dithering. */
|
|
7
3
|
export declare function applyThresholdMap(pixels: ArrayOrBuffer<number>, width: number, map: number[][]): void;
|
|
8
4
|
/** Applies an error diffusion kernel to raw pixel data. */
|
|
9
5
|
export declare function applyDiffusionKernel(pixels: ArrayOrBuffer<number>, width: number, height: number, kernel: number[][]): void;
|
|
10
|
-
export {};
|
package/dist/threshold-maps.json
CHANGED
|
@@ -125,11 +125,6 @@
|
|
|
125
125
|
[224, 140, 56, 14, 98, 182],
|
|
126
126
|
[238, 154, 70, 28, 112, 196]
|
|
127
127
|
],
|
|
128
|
-
"dot-vertical-5x3": [
|
|
129
|
-
[153, 51, 0, 102, 204],
|
|
130
|
-
[170, 68, 17, 119, 221],
|
|
131
|
-
[187, 85, 34, 136, 238]
|
|
132
|
-
],
|
|
133
128
|
"dot-horizontal-3x5": [
|
|
134
129
|
[153, 170, 187],
|
|
135
130
|
[51, 68, 85],
|
|
@@ -137,6 +132,33 @@
|
|
|
137
132
|
[102, 119, 136],
|
|
138
133
|
[204, 221, 238]
|
|
139
134
|
],
|
|
135
|
+
"dot-vertical-5x3": [
|
|
136
|
+
[153, 51, 0, 102, 204],
|
|
137
|
+
[170, 68, 17, 119, 221],
|
|
138
|
+
[187, 85, 34, 136, 238]
|
|
139
|
+
],
|
|
140
|
+
"horizontal-checkers-6": [
|
|
141
|
+
[245, 231, 217, 210, 224, 238, 35, 21, 7, 0, 14, 28],
|
|
142
|
+
[161, 147, 133, 126, 140, 154, 119, 105, 91, 84, 98, 112],
|
|
143
|
+
[77, 63, 49, 42, 56, 70, 203, 189, 175, 168, 182, 196],
|
|
144
|
+
[35, 21, 7, 0, 14, 28, 245, 231, 217, 210, 224, 238],
|
|
145
|
+
[119, 105, 91, 84, 98, 112, 161, 147, 133, 126, 140, 154],
|
|
146
|
+
[203, 189, 175, 168, 182, 196, 77, 63, 49, 42, 56, 70]
|
|
147
|
+
],
|
|
148
|
+
"vertical-checkers-6": [
|
|
149
|
+
[245, 161, 77, 35, 119, 203],
|
|
150
|
+
[231, 147, 63, 21, 105, 189],
|
|
151
|
+
[217, 133, 49, 7, 91, 175],
|
|
152
|
+
[210, 126, 42, 0, 84, 168],
|
|
153
|
+
[224, 140, 56, 14, 98, 182],
|
|
154
|
+
[238, 154, 70, 28, 112, 196],
|
|
155
|
+
[35, 119, 203, 245, 161, 77],
|
|
156
|
+
[21, 105, 189, 231, 147, 63],
|
|
157
|
+
[7, 91, 175, 217, 133, 49],
|
|
158
|
+
[0, 84, 168, 210, 126, 42],
|
|
159
|
+
[14, 98, 182, 224, 140, 56],
|
|
160
|
+
[28, 112, 196, 238, 154, 70]
|
|
161
|
+
],
|
|
140
162
|
"blue-noise": [
|
|
141
163
|
[
|
|
142
164
|
134, 22, 92, 59, 163, 190, 12, 155, 181, 119, 233, 47, 175, 12, 113, 141, 47, 183, 111, 196,
|
package/dist/types.d.ts
CHANGED
|
@@ -37,3 +37,8 @@ export interface SweetcornOptions {
|
|
|
37
37
|
*/
|
|
38
38
|
diffusionKernel?: number[][] | undefined;
|
|
39
39
|
}
|
|
40
|
+
/** Any array-like structure indexed by numbers and with a `length`, e.g. an `Array` or `Buffer`. */
|
|
41
|
+
export interface ArrayOrBuffer<T> {
|
|
42
|
+
length: number;
|
|
43
|
+
[n: number]: T;
|
|
44
|
+
}
|