@opendisplay/epaper-dithering 2.1.4 → 2.2.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/dist/index.js CHANGED
@@ -12,6 +12,159 @@ var DitherMode = /* @__PURE__ */ ((DitherMode2) => {
12
12
  return DitherMode2;
13
13
  })(DitherMode || {});
14
14
 
15
+ // src/color_space.ts
16
+ var SRGB_TO_LINEAR_LUT = (() => {
17
+ const lut = new Float64Array(256);
18
+ for (let i = 0; i < 256; i++) {
19
+ const s = i / 255;
20
+ lut[i] = s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
21
+ }
22
+ return lut;
23
+ })();
24
+
25
+ // src/color_space_lab.ts
26
+ var M00 = 0.4124564;
27
+ var M01 = 0.3575761;
28
+ var M02 = 0.1804375;
29
+ var M10 = 0.2126729;
30
+ var M11 = 0.7151522;
31
+ var M12 = 0.072175;
32
+ var M20 = 0.0193339;
33
+ var M21 = 0.119192;
34
+ var M22 = 0.9503041;
35
+ var XN = 0.95047;
36
+ var YN = 1;
37
+ var ZN = 1.08883;
38
+ var EPSILON = 216 / 24389;
39
+ var KAPPA = 24389 / 27;
40
+ var WL2 = 0.25;
41
+ var WC2 = 1;
42
+ var WH2 = 4;
43
+ function labF(t) {
44
+ return t > EPSILON ? Math.cbrt(t) : (KAPPA * t + 16) / 116;
45
+ }
46
+ function rgbToLabScalar(r, g, b) {
47
+ const x = M00 * r + M01 * g + M02 * b;
48
+ const y = M10 * r + M11 * g + M12 * b;
49
+ const z = M20 * r + M21 * g + M22 * b;
50
+ const fx = labF(x / XN);
51
+ const fy = labF(y / YN);
52
+ const fz = labF(z / ZN);
53
+ return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)];
54
+ }
55
+ function precomputePaletteLab(paletteLinear) {
56
+ const n = paletteLinear.length;
57
+ const L = new Float64Array(n);
58
+ const a = new Float64Array(n);
59
+ const b = new Float64Array(n);
60
+ const C = new Float64Array(n);
61
+ for (let i = 0; i < n; i++) {
62
+ const [pl, pa, pb] = rgbToLabScalar(paletteLinear[i][0], paletteLinear[i][1], paletteLinear[i][2]);
63
+ L[i] = pl;
64
+ a[i] = pa;
65
+ b[i] = pb;
66
+ C[i] = Math.sqrt(pa * pa + pb * pb);
67
+ }
68
+ return { L, a, b, C };
69
+ }
70
+ function matchPixelLch(r, g, b, paletteL, paletteA, paletteB, paletteC) {
71
+ const [pL, pa, pb] = rgbToLabScalar(r, g, b);
72
+ const pC = Math.sqrt(pa * pa + pb * pb);
73
+ let bestIdx = 0;
74
+ let bestDist = Infinity;
75
+ const n = paletteL.length;
76
+ for (let i = 0; i < n; i++) {
77
+ const dL = pL - paletteL[i];
78
+ const da = pa - paletteA[i];
79
+ const db = pb - paletteB[i];
80
+ const dC = pC - paletteC[i];
81
+ let dHsq = da * da + db * db - dC * dC;
82
+ if (dHsq < 0) dHsq = 0;
83
+ const dist = WL2 * dL * dL + WC2 * dC * dC + WH2 * dHsq;
84
+ if (dist < bestDist) {
85
+ bestDist = dist;
86
+ bestIdx = i;
87
+ }
88
+ }
89
+ return bestIdx;
90
+ }
91
+
92
+ // src/tone_map.ts
93
+ var LUM_R = 0.2126729;
94
+ var LUM_G = 0.7151522;
95
+ var LUM_B = 0.072175;
96
+ function compressDynamicRange(pixels, width, height, paletteLinear, strength = 1) {
97
+ if (strength <= 0) return;
98
+ const [br, bg, bb] = paletteLinear[0];
99
+ const [wr, wg, wb] = paletteLinear[1];
100
+ const blackY = LUM_R * br + LUM_G * bg + LUM_B * bb;
101
+ const whiteY = LUM_R * wr + LUM_G * wg + LUM_B * wb;
102
+ const displayRange = whiteY - blackY;
103
+ if (displayRange <= 0) return;
104
+ const n = width * height;
105
+ const blackLevel = blackY * strength;
106
+ for (let i = 0; i < n; i++) {
107
+ const base = i * 3;
108
+ const r = pixels[base];
109
+ const g = pixels[base + 1];
110
+ const b = pixels[base + 2];
111
+ const Y = LUM_R * r + LUM_G * g + LUM_B * b;
112
+ if (Y > 1e-6) {
113
+ const compressedY = blackY + Y * displayRange;
114
+ const targetY = strength < 1 ? Y + strength * (compressedY - Y) : compressedY;
115
+ const scale = targetY / Y;
116
+ pixels[base] = Math.max(0, Math.min(1, r * scale));
117
+ pixels[base + 1] = Math.max(0, Math.min(1, g * scale));
118
+ pixels[base + 2] = Math.max(0, Math.min(1, b * scale));
119
+ } else {
120
+ pixels[base] = blackLevel;
121
+ pixels[base + 1] = blackLevel;
122
+ pixels[base + 2] = blackLevel;
123
+ }
124
+ }
125
+ }
126
+ function autoCompressDynamicRange(pixels, width, height, paletteLinear) {
127
+ const [br, bg, bb] = paletteLinear[0];
128
+ const [wr, wg, wb] = paletteLinear[1];
129
+ const blackY = LUM_R * br + LUM_G * bg + LUM_B * bb;
130
+ const whiteY = LUM_R * wr + LUM_G * wg + LUM_B * wb;
131
+ const displayRange = whiteY - blackY;
132
+ if (displayRange <= 0) return;
133
+ const n = width * height;
134
+ const luminances = new Float32Array(n);
135
+ for (let i = 0; i < n; i++) {
136
+ const base = i * 3;
137
+ luminances[i] = LUM_R * pixels[base] + LUM_G * pixels[base + 1] + LUM_B * pixels[base + 2];
138
+ }
139
+ luminances.sort();
140
+ const pLow = luminances[Math.floor(n * 0.02)];
141
+ const pHigh = luminances[Math.floor(n * 0.98)];
142
+ const imageRange = pHigh - pLow;
143
+ if (imageRange < 1e-6) {
144
+ compressDynamicRange(pixels, width, height, paletteLinear, 1);
145
+ return;
146
+ }
147
+ for (let i = 0; i < n; i++) {
148
+ const base = i * 3;
149
+ const r = pixels[base];
150
+ const g = pixels[base + 1];
151
+ const b = pixels[base + 2];
152
+ const Y = LUM_R * r + LUM_G * g + LUM_B * b;
153
+ if (Y > 1e-6) {
154
+ const normalizedY = (Y - pLow) / imageRange;
155
+ const targetY = blackY + normalizedY * displayRange;
156
+ const scale = targetY / Y;
157
+ pixels[base] = Math.max(0, Math.min(1, r * scale));
158
+ pixels[base + 1] = Math.max(0, Math.min(1, g * scale));
159
+ pixels[base + 2] = Math.max(0, Math.min(1, b * scale));
160
+ } else {
161
+ pixels[base] = blackY;
162
+ pixels[base + 1] = blackY;
163
+ pixels[base + 2] = blackY;
164
+ }
165
+ }
166
+ }
167
+
15
168
  // src/palettes.ts
16
169
  var ColorScheme = /* @__PURE__ */ ((ColorScheme3) => {
17
170
  ColorScheme3[ColorScheme3["MONO"] = 0] = "MONO";
@@ -20,6 +173,8 @@ var ColorScheme = /* @__PURE__ */ ((ColorScheme3) => {
20
173
  ColorScheme3[ColorScheme3["BWRY"] = 3] = "BWRY";
21
174
  ColorScheme3[ColorScheme3["BWGBRY"] = 4] = "BWGBRY";
22
175
  ColorScheme3[ColorScheme3["GRAYSCALE_4"] = 5] = "GRAYSCALE_4";
176
+ ColorScheme3[ColorScheme3["GRAYSCALE_8"] = 6] = "GRAYSCALE_8";
177
+ ColorScheme3[ColorScheme3["GRAYSCALE_16"] = 7] = "GRAYSCALE_16";
23
178
  return ColorScheme3;
24
179
  })(ColorScheme || {});
25
180
  var PALETTES = {
@@ -74,6 +229,40 @@ var PALETTES = {
74
229
  white: { r: 255, g: 255, b: 255 }
75
230
  },
76
231
  accent: "black"
232
+ },
233
+ [6 /* GRAYSCALE_8 */]: {
234
+ colors: {
235
+ black: { r: 0, g: 0, b: 0 },
236
+ gray1: { r: 36, g: 36, b: 36 },
237
+ gray2: { r: 73, g: 73, b: 73 },
238
+ gray3: { r: 109, g: 109, b: 109 },
239
+ gray4: { r: 146, g: 146, b: 146 },
240
+ gray5: { r: 182, g: 182, b: 182 },
241
+ gray6: { r: 219, g: 219, b: 219 },
242
+ white: { r: 255, g: 255, b: 255 }
243
+ },
244
+ accent: "black"
245
+ },
246
+ [7 /* GRAYSCALE_16 */]: {
247
+ colors: {
248
+ black: { r: 0, g: 0, b: 0 },
249
+ gray1: { r: 17, g: 17, b: 17 },
250
+ gray2: { r: 34, g: 34, b: 34 },
251
+ gray3: { r: 51, g: 51, b: 51 },
252
+ gray4: { r: 68, g: 68, b: 68 },
253
+ gray5: { r: 85, g: 85, b: 85 },
254
+ gray6: { r: 102, g: 102, b: 102 },
255
+ gray7: { r: 119, g: 119, b: 119 },
256
+ gray8: { r: 136, g: 136, b: 136 },
257
+ gray9: { r: 153, g: 153, b: 153 },
258
+ gray10: { r: 170, g: 170, b: 170 },
259
+ gray11: { r: 187, g: 187, b: 187 },
260
+ gray12: { r: 204, g: 204, b: 204 },
261
+ gray13: { r: 221, g: 221, b: 221 },
262
+ gray14: { r: 238, g: 238, b: 238 },
263
+ white: { r: 255, g: 255, b: 255 }
264
+ },
265
+ accent: "black"
77
266
  }
78
267
  };
79
268
  function getPalette(scheme) {
@@ -83,143 +272,230 @@ function getColorCount(scheme) {
83
272
  return Object.keys(PALETTES[scheme].colors).length;
84
273
  }
85
274
  function fromValue(value) {
86
- if (value < 0 || value > 5) {
275
+ if (value < 0 || value > 7) {
87
276
  throw new Error(`Invalid color scheme value: ${value}`);
88
277
  }
89
278
  return value;
90
279
  }
280
+ var SPECTRA_7_3_6COLOR = {
281
+ colors: {
282
+ black: { r: 26, g: 13, b: 35 },
283
+ white: { r: 185, g: 202, b: 205 },
284
+ yellow: { r: 202, g: 184, b: 0 },
285
+ red: { r: 121, g: 9, b: 0 },
286
+ blue: { r: 0, g: 69, b: 139 },
287
+ green: { r: 40, g: 82, b: 57 }
288
+ },
289
+ accent: "red"
290
+ };
291
+ var MONO_4_26 = {
292
+ colors: {
293
+ black: { r: 5, g: 5, b: 5 },
294
+ white: { r: 220, g: 220, b: 220 }
295
+ },
296
+ accent: "black"
297
+ };
298
+ var BWRY_4_2 = {
299
+ colors: {
300
+ black: { r: 5, g: 5, b: 5 },
301
+ white: { r: 200, g: 200, b: 200 },
302
+ yellow: { r: 200, g: 180, b: 0 },
303
+ red: { r: 120, g: 15, b: 5 }
304
+ },
305
+ accent: "red"
306
+ };
307
+ var SOLUM_BWR = {
308
+ colors: {
309
+ black: { r: 5, g: 5, b: 5 },
310
+ white: { r: 200, g: 200, b: 200 },
311
+ red: { r: 120, g: 15, b: 5 }
312
+ },
313
+ accent: "red"
314
+ };
315
+ var HANSHOW_BWR = {
316
+ colors: {
317
+ black: { r: 5, g: 5, b: 5 },
318
+ white: { r: 200, g: 200, b: 200 },
319
+ red: { r: 120, g: 15, b: 5 }
320
+ },
321
+ accent: "red"
322
+ };
323
+ var HANSHOW_BWY = {
324
+ colors: {
325
+ black: { r: 5, g: 5, b: 5 },
326
+ white: { r: 200, g: 200, b: 200 },
327
+ yellow: { r: 200, g: 180, b: 0 }
328
+ },
329
+ accent: "yellow"
330
+ };
331
+ var BWRY_3_97 = {
332
+ colors: {
333
+ black: { r: 10, g: 7, b: 14 },
334
+ white: { r: 173, g: 178, b: 174 },
335
+ yellow: { r: 172, g: 128, b: 0 },
336
+ red: { r: 85, g: 24, b: 14 }
337
+ },
338
+ accent: "red"
339
+ };
91
340
 
92
341
  // src/algorithms.ts
93
- function getPaletteColors(scheme) {
94
- const palette = getPalette(scheme);
95
- return Object.values(palette.colors);
342
+ var BAYER_4X4 = new Float32Array([
343
+ 0,
344
+ 8,
345
+ 2,
346
+ 10,
347
+ 12,
348
+ 4,
349
+ 14,
350
+ 6,
351
+ 3,
352
+ 11,
353
+ 1,
354
+ 9,
355
+ 15,
356
+ 7,
357
+ 13,
358
+ 5
359
+ ].map((v) => v / 16 - 0.5));
360
+ function resolvePalette(scheme) {
361
+ return typeof scheme === "number" ? getPalette(scheme) : scheme;
96
362
  }
97
- function findClosestPaletteColor(rgb, palette) {
98
- let minDistance = Infinity;
99
- let closestIdx = 0;
100
- for (let i = 0; i < palette.length; i++) {
101
- const pal = palette[i];
102
- const distance = (rgb.r - pal.r) ** 2 + (rgb.g - pal.g) ** 2 + (rgb.b - pal.b) ** 2;
103
- if (distance < minDistance) {
104
- minDistance = distance;
105
- closestIdx = i;
106
- }
363
+ function paletteToLinear(palette) {
364
+ const paletteRgb = Object.values(palette.colors);
365
+ const paletteLinear = paletteRgb.map((c) => [
366
+ SRGB_TO_LINEAR_LUT[c.r],
367
+ SRGB_TO_LINEAR_LUT[c.g],
368
+ SRGB_TO_LINEAR_LUT[c.b]
369
+ ]);
370
+ return { paletteRgb, paletteLinear };
371
+ }
372
+ function buildLinearBuffer(image) {
373
+ const n = image.width * image.height;
374
+ const pixels = new Float32Array(n * 3);
375
+ const { data } = image;
376
+ for (let i = 0; i < n; i++) {
377
+ const base4 = i * 4;
378
+ const base3 = i * 3;
379
+ const alpha = data[base4 + 3] / 255;
380
+ const inv = 1 - alpha;
381
+ pixels[base3] = SRGB_TO_LINEAR_LUT[data[base4]] * alpha + inv;
382
+ pixels[base3 + 1] = SRGB_TO_LINEAR_LUT[data[base4 + 1]] * alpha + inv;
383
+ pixels[base3 + 2] = SRGB_TO_LINEAR_LUT[data[base4 + 2]] * alpha + inv;
107
384
  }
108
- return closestIdx;
385
+ return pixels;
109
386
  }
110
- function errorDiffusionDither(image, colorScheme, kernel) {
387
+ function errorDiffusionDither(image, scheme, kernel, serpentine) {
111
388
  const { width, height } = image;
112
- const palette = getPaletteColors(colorScheme);
113
- const pixels = new Float32Array(width * height * 3);
114
- for (let i = 0; i < width * height; i++) {
115
- pixels[i * 3] = image.data[i * 4];
116
- pixels[i * 3 + 1] = image.data[i * 4 + 1];
117
- pixels[i * 3 + 2] = image.data[i * 4 + 2];
389
+ const palette = resolvePalette(scheme);
390
+ const { paletteRgb, paletteLinear } = paletteToLinear(palette);
391
+ const numColors = paletteRgb.length;
392
+ const pixels = buildLinearBuffer(image);
393
+ if (typeof scheme !== "number") {
394
+ autoCompressDynamicRange(pixels, width, height, paletteLinear);
395
+ }
396
+ const { L: palL, a: palA, b: palB, C: palC } = precomputePaletteLab(paletteLinear);
397
+ const palR = new Float64Array(numColors);
398
+ const palG = new Float64Array(numColors);
399
+ const palBl = new Float64Array(numColors);
400
+ for (let i = 0; i < numColors; i++) {
401
+ palR[i] = paletteLinear[i][0];
402
+ palG[i] = paletteLinear[i][1];
403
+ palBl[i] = paletteLinear[i][2];
118
404
  }
119
405
  const indices = new Uint8Array(width * height);
120
406
  for (let y = 0; y < height; y++) {
121
- for (let x = 0; x < width; x++) {
122
- const idx = y * width + x;
123
- const pixelIdx = idx * 3;
124
- const oldPixel = {
125
- r: Math.trunc(pixels[pixelIdx]),
126
- g: Math.trunc(pixels[pixelIdx + 1]),
127
- b: Math.trunc(pixels[pixelIdx + 2])
128
- };
129
- const newIdx = findClosestPaletteColor(oldPixel, palette);
130
- const newPixel = palette[newIdx];
131
- indices[idx] = newIdx;
132
- const errorR = oldPixel.r - newPixel.r;
133
- const errorG = oldPixel.g - newPixel.g;
134
- const errorB = oldPixel.b - newPixel.b;
135
- for (const { dx, dy, weight } of kernel) {
136
- const nx = x + dx;
137
- const ny = y + dy;
407
+ const leftToRight = !serpentine || y % 2 === 0;
408
+ const xStart = leftToRight ? 0 : width - 1;
409
+ const xEnd = leftToRight ? width : -1;
410
+ const xStep = leftToRight ? 1 : -1;
411
+ for (let x = xStart; x !== xEnd; x += xStep) {
412
+ const pixIdx = (y * width + x) * 3;
413
+ const r = Math.max(0, Math.min(1, pixels[pixIdx]));
414
+ const g = Math.max(0, Math.min(1, pixels[pixIdx + 1]));
415
+ const b = Math.max(0, Math.min(1, pixels[pixIdx + 2]));
416
+ const newIdx = matchPixelLch(r, g, b, palL, palA, palB, palC);
417
+ indices[y * width + x] = newIdx;
418
+ const errR = r - palR[newIdx];
419
+ const errG = g - palG[newIdx];
420
+ const errB = b - palBl[newIdx];
421
+ for (let k = 0; k < kernel.length; k++) {
422
+ const kEntry = kernel[k];
423
+ const nx = x + (leftToRight ? kEntry.dx : -kEntry.dx);
424
+ const ny = y + kEntry.dy;
138
425
  if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
139
- const neighborIdx = (ny * width + nx) * 3;
140
- pixels[neighborIdx] += errorR * weight;
141
- pixels[neighborIdx + 1] += errorG * weight;
142
- pixels[neighborIdx + 2] += errorB * weight;
426
+ const nIdx = (ny * width + nx) * 3;
427
+ pixels[nIdx] += errR * kEntry.weight;
428
+ pixels[nIdx + 1] += errG * kEntry.weight;
429
+ pixels[nIdx + 2] += errB * kEntry.weight;
143
430
  }
144
431
  }
145
432
  }
146
433
  }
147
- return { width, height, indices, palette };
434
+ return { width, height, indices, palette: paletteRgb };
148
435
  }
149
- function directPaletteMap(image, colorScheme) {
436
+ function directPaletteMap(image, scheme) {
150
437
  const { width, height } = image;
151
- const palette = getPaletteColors(colorScheme);
438
+ const palette = resolvePalette(scheme);
439
+ const { paletteRgb, paletteLinear } = paletteToLinear(palette);
440
+ const pixels = buildLinearBuffer(image);
441
+ if (typeof scheme !== "number") {
442
+ autoCompressDynamicRange(pixels, width, height, paletteLinear);
443
+ }
444
+ const { L: palL, a: palA, b: palB, C: palC } = precomputePaletteLab(paletteLinear);
152
445
  const indices = new Uint8Array(width * height);
153
- for (let i = 0; i < width * height; i++) {
154
- const rgb = {
155
- r: image.data[i * 4],
156
- g: image.data[i * 4 + 1],
157
- b: image.data[i * 4 + 2]
158
- };
159
- indices[i] = findClosestPaletteColor(rgb, palette);
446
+ const n = width * height;
447
+ for (let i = 0; i < n; i++) {
448
+ const base = i * 3;
449
+ const r = Math.max(0, Math.min(1, pixels[base]));
450
+ const g = Math.max(0, Math.min(1, pixels[base + 1]));
451
+ const b = Math.max(0, Math.min(1, pixels[base + 2]));
452
+ indices[i] = matchPixelLch(r, g, b, palL, palA, palB, palC);
160
453
  }
161
- return { width, height, indices, palette };
454
+ return { width, height, indices, palette: paletteRgb };
162
455
  }
163
- function orderedDither(image, colorScheme) {
164
- const bayerMatrix = new Uint8Array([
165
- 0,
166
- 8,
167
- 2,
168
- 10,
169
- 12,
170
- 4,
171
- 14,
172
- 6,
173
- 3,
174
- 11,
175
- 1,
176
- 9,
177
- 15,
178
- 7,
179
- 13,
180
- 5
181
- ]).map((v) => v * 16);
456
+ function orderedDither(image, scheme) {
182
457
  const { width, height } = image;
183
- const palette = getPaletteColors(colorScheme);
458
+ const palette = resolvePalette(scheme);
459
+ const { paletteRgb, paletteLinear } = paletteToLinear(palette);
460
+ const pixels = buildLinearBuffer(image);
461
+ if (typeof scheme !== "number") {
462
+ autoCompressDynamicRange(pixels, width, height, paletteLinear);
463
+ }
464
+ const { L: palL, a: palA, b: palB, C: palC } = precomputePaletteLab(paletteLinear);
184
465
  const indices = new Uint8Array(width * height);
185
466
  for (let y = 0; y < height; y++) {
186
467
  for (let x = 0; x < width; x++) {
187
- const idx = y * width + x;
188
- const dataIdx = idx * 4;
189
- const threshold = bayerMatrix[y % 4 * 4 + x % 4];
190
- const rgb = {
191
- r: Math.max(0, Math.min(255, Math.trunc(image.data[dataIdx] + threshold))),
192
- g: Math.max(0, Math.min(255, Math.trunc(image.data[dataIdx + 1] + threshold))),
193
- b: Math.max(0, Math.min(255, Math.trunc(image.data[dataIdx + 2] + threshold)))
194
- };
195
- indices[idx] = findClosestPaletteColor(rgb, palette);
468
+ const base = (y * width + x) * 3;
469
+ const threshold = BAYER_4X4[y % 4 * 4 + x % 4];
470
+ const r = Math.max(0, Math.min(1, pixels[base] + threshold));
471
+ const g = Math.max(0, Math.min(1, pixels[base + 1] + threshold));
472
+ const b = Math.max(0, Math.min(1, pixels[base + 2] + threshold));
473
+ indices[y * width + x] = matchPixelLch(r, g, b, palL, palA, palB, palC);
196
474
  }
197
475
  }
198
- return { width, height, indices, palette };
476
+ return { width, height, indices, palette: paletteRgb };
199
477
  }
200
- function burkesDither(image, colorScheme) {
201
- const kernel = [
202
- { dx: 1, dy: 0, weight: 32 / 200 },
203
- { dx: 2, dy: 0, weight: 12 / 200 },
204
- { dx: -2, dy: 1, weight: 5 / 200 },
205
- { dx: -1, dy: 1, weight: 12 / 200 },
206
- { dx: 0, dy: 1, weight: 26 / 200 },
207
- { dx: 1, dy: 1, weight: 12 / 200 },
208
- { dx: 2, dy: 1, weight: 5 / 200 }
209
- ];
210
- return errorDiffusionDither(image, colorScheme, kernel);
211
- }
212
- function floydSteinbergDither(image, colorScheme) {
213
- const kernel = [
478
+ function floydSteinbergDither(image, scheme, serpentine = true) {
479
+ return errorDiffusionDither(image, scheme, [
214
480
  { dx: 1, dy: 0, weight: 7 / 16 },
215
481
  { dx: -1, dy: 1, weight: 3 / 16 },
216
482
  { dx: 0, dy: 1, weight: 5 / 16 },
217
483
  { dx: 1, dy: 1, weight: 1 / 16 }
218
- ];
219
- return errorDiffusionDither(image, colorScheme, kernel);
484
+ ], serpentine);
485
+ }
486
+ function burkesDither(image, scheme, serpentine = true) {
487
+ return errorDiffusionDither(image, scheme, [
488
+ { dx: 1, dy: 0, weight: 8 / 32 },
489
+ { dx: 2, dy: 0, weight: 4 / 32 },
490
+ { dx: -2, dy: 1, weight: 2 / 32 },
491
+ { dx: -1, dy: 1, weight: 4 / 32 },
492
+ { dx: 0, dy: 1, weight: 8 / 32 },
493
+ { dx: 1, dy: 1, weight: 4 / 32 },
494
+ { dx: 2, dy: 1, weight: 2 / 32 }
495
+ ], serpentine);
220
496
  }
221
- function sierraDither(image, colorScheme) {
222
- const kernel = [
497
+ function sierraDither(image, scheme, serpentine = true) {
498
+ return errorDiffusionDither(image, scheme, [
223
499
  { dx: 1, dy: 0, weight: 5 / 32 },
224
500
  { dx: 2, dy: 0, weight: 3 / 32 },
225
501
  { dx: -2, dy: 1, weight: 2 / 32 },
@@ -230,30 +506,27 @@ function sierraDither(image, colorScheme) {
230
506
  { dx: -1, dy: 2, weight: 2 / 32 },
231
507
  { dx: 0, dy: 2, weight: 3 / 32 },
232
508
  { dx: 1, dy: 2, weight: 2 / 32 }
233
- ];
234
- return errorDiffusionDither(image, colorScheme, kernel);
509
+ ], serpentine);
235
510
  }
236
- function sierraLiteDither(image, colorScheme) {
237
- const kernel = [
511
+ function sierraLiteDither(image, scheme, serpentine = true) {
512
+ return errorDiffusionDither(image, scheme, [
238
513
  { dx: 1, dy: 0, weight: 2 / 4 },
239
514
  { dx: -1, dy: 1, weight: 1 / 4 },
240
515
  { dx: 0, dy: 1, weight: 1 / 4 }
241
- ];
242
- return errorDiffusionDither(image, colorScheme, kernel);
516
+ ], serpentine);
243
517
  }
244
- function atkinsonDither(image, colorScheme) {
245
- const kernel = [
518
+ function atkinsonDither(image, scheme, serpentine = true) {
519
+ return errorDiffusionDither(image, scheme, [
246
520
  { dx: 1, dy: 0, weight: 1 / 8 },
247
521
  { dx: 2, dy: 0, weight: 1 / 8 },
248
522
  { dx: -1, dy: 1, weight: 1 / 8 },
249
523
  { dx: 0, dy: 1, weight: 1 / 8 },
250
524
  { dx: 1, dy: 1, weight: 1 / 8 },
251
525
  { dx: 0, dy: 2, weight: 1 / 8 }
252
- ];
253
- return errorDiffusionDither(image, colorScheme, kernel);
526
+ ], serpentine);
254
527
  }
255
- function stuckiDither(image, colorScheme) {
256
- const kernel = [
528
+ function stuckiDither(image, scheme, serpentine = true) {
529
+ return errorDiffusionDither(image, scheme, [
257
530
  { dx: 1, dy: 0, weight: 8 / 42 },
258
531
  { dx: 2, dy: 0, weight: 4 / 42 },
259
532
  { dx: -2, dy: 1, weight: 2 / 42 },
@@ -266,11 +539,10 @@ function stuckiDither(image, colorScheme) {
266
539
  { dx: 0, dy: 2, weight: 4 / 42 },
267
540
  { dx: 1, dy: 2, weight: 2 / 42 },
268
541
  { dx: 2, dy: 2, weight: 1 / 42 }
269
- ];
270
- return errorDiffusionDither(image, colorScheme, kernel);
542
+ ], serpentine);
271
543
  }
272
- function jarvisJudiceNinkeDither(image, colorScheme) {
273
- const kernel = [
544
+ function jarvisJudiceNinkeDither(image, scheme, serpentine = true) {
545
+ return errorDiffusionDither(image, scheme, [
274
546
  { dx: 1, dy: 0, weight: 7 / 48 },
275
547
  { dx: 2, dy: 0, weight: 5 / 48 },
276
548
  { dx: -2, dy: 1, weight: 3 / 48 },
@@ -283,38 +555,37 @@ function jarvisJudiceNinkeDither(image, colorScheme) {
283
555
  { dx: 0, dy: 2, weight: 5 / 48 },
284
556
  { dx: 1, dy: 2, weight: 3 / 48 },
285
557
  { dx: 2, dy: 2, weight: 1 / 48 }
286
- ];
287
- return errorDiffusionDither(image, colorScheme, kernel);
558
+ ], serpentine);
288
559
  }
289
560
 
290
561
  // src/core.ts
291
- function ditherImage(image, colorScheme, mode = 1 /* BURKES */) {
562
+ function ditherImage(image, colorScheme, mode = 1 /* BURKES */, serpentine = true) {
292
563
  switch (mode) {
293
564
  case 0 /* NONE */:
294
565
  return directPaletteMap(image, colorScheme);
295
566
  case 2 /* ORDERED */:
296
567
  return orderedDither(image, colorScheme);
297
568
  case 3 /* FLOYD_STEINBERG */:
298
- return floydSteinbergDither(image, colorScheme);
569
+ return floydSteinbergDither(image, colorScheme, serpentine);
299
570
  case 4 /* ATKINSON */:
300
- return atkinsonDither(image, colorScheme);
571
+ return atkinsonDither(image, colorScheme, serpentine);
301
572
  case 5 /* STUCKI */:
302
- return stuckiDither(image, colorScheme);
573
+ return stuckiDither(image, colorScheme, serpentine);
303
574
  case 6 /* SIERRA */:
304
- return sierraDither(image, colorScheme);
575
+ return sierraDither(image, colorScheme, serpentine);
305
576
  case 7 /* SIERRA_LITE */:
306
- return sierraLiteDither(image, colorScheme);
577
+ return sierraLiteDither(image, colorScheme, serpentine);
307
578
  case 8 /* JARVIS_JUDICE_NINKE */:
308
- return jarvisJudiceNinkeDither(image, colorScheme);
579
+ return jarvisJudiceNinkeDither(image, colorScheme, serpentine);
309
580
  case 1 /* BURKES */:
310
581
  default:
311
- return burkesDither(image, colorScheme);
582
+ return burkesDither(image, colorScheme, serpentine);
312
583
  }
313
584
  }
314
585
 
315
586
  // src/index.ts
316
587
  var VERSION = "0.1.0";
317
588
 
318
- export { ColorScheme, DitherMode, VERSION, ditherImage, fromValue, getColorCount, getPalette };
589
+ export { BWRY_3_97, BWRY_4_2, ColorScheme, DitherMode, HANSHOW_BWR, HANSHOW_BWY, MONO_4_26, SOLUM_BWR, SPECTRA_7_3_6COLOR, VERSION, ditherImage, fromValue, getColorCount, getPalette };
319
590
  //# sourceMappingURL=index.js.map
320
591
  //# sourceMappingURL=index.js.map