@xprite/pixelate 0.0.0-stage → 0.1.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.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +12 -0
  3. package/README.md +270 -2
  4. package/README.zh-CN.md +240 -0
  5. package/dist/analyze.d.ts +8 -0
  6. package/dist/analyze.js +217 -0
  7. package/dist/base.d.ts +18 -0
  8. package/dist/base.js +42 -0
  9. package/dist/cell-color-picker.d.ts +14 -0
  10. package/dist/cell-color-picker.js +278 -0
  11. package/dist/color-lab.d.ts +3 -0
  12. package/dist/color-lab.js +31 -0
  13. package/dist/color-step.d.ts +33 -0
  14. package/dist/color-step.js +62 -0
  15. package/dist/contours.d.ts +4 -0
  16. package/dist/contours.js +66 -0
  17. package/dist/denoise.d.ts +3 -0
  18. package/dist/denoise.js +37 -0
  19. package/dist/deskew.d.ts +24 -0
  20. package/dist/deskew.js +202 -0
  21. package/dist/grid-ac-rl-consensus.d.ts +127 -0
  22. package/dist/grid-ac-rl-consensus.js +497 -0
  23. package/dist/grid-arbitrate.d.ts +52 -0
  24. package/dist/grid-arbitrate.js +366 -0
  25. package/dist/grid-cut-snap.d.ts +15 -0
  26. package/dist/grid-cut-snap.js +77 -0
  27. package/dist/grid-description-length.d.ts +47 -0
  28. package/dist/grid-description-length.js +697 -0
  29. package/dist/grid-detect.d.ts +8 -0
  30. package/dist/grid-detect.js +665 -0
  31. package/dist/grid-edge-coherence.d.ts +4 -0
  32. package/dist/grid-edge-coherence.js +158 -0
  33. package/dist/grid-edge-path.d.ts +9 -0
  34. package/dist/grid-edge-path.js +201 -0
  35. package/dist/grid-frame-lattice.d.ts +25 -0
  36. package/dist/grid-frame-lattice.js +420 -0
  37. package/dist/grid-frequency-spectrum.d.ts +11 -0
  38. package/dist/grid-frequency-spectrum.js +89 -0
  39. package/dist/grid-period-boundary.d.ts +13 -0
  40. package/dist/grid-period-boundary.js +255 -0
  41. package/dist/grid-period-comb.d.ts +4 -0
  42. package/dist/grid-period-comb.js +230 -0
  43. package/dist/grid-period-distance.d.ts +7 -0
  44. package/dist/grid-period-distance.js +233 -0
  45. package/dist/grid-phase-field.d.ts +11 -0
  46. package/dist/grid-phase-field.js +446 -0
  47. package/dist/grid-pitch-lattice.d.ts +4 -0
  48. package/dist/grid-pitch-lattice.js +255 -0
  49. package/dist/grid-pitch-search.d.ts +11 -0
  50. package/dist/grid-pitch-search.js +233 -0
  51. package/dist/grid-sample.d.ts +4 -0
  52. package/dist/grid-sample.js +164 -0
  53. package/dist/grid-sampling.d.ts +13 -0
  54. package/dist/grid-sampling.js +132 -0
  55. package/dist/grid-strip-shift.d.ts +44 -0
  56. package/dist/grid-strip-shift.js +223 -0
  57. package/dist/grid-test-images.d.ts +69 -0
  58. package/dist/grid-test-images.js +547 -0
  59. package/dist/grid-warp.d.ts +38 -0
  60. package/dist/grid-warp.js +252 -0
  61. package/dist/grid.d.ts +8 -0
  62. package/dist/grid.js +43 -0
  63. package/dist/index.d.ts +16 -0
  64. package/dist/index.js +14 -0
  65. package/dist/line-guided/cv-lab.d.ts +4 -0
  66. package/dist/line-guided/cv-lab.js +134 -0
  67. package/dist/line-guided/cv-ops.d.ts +29 -0
  68. package/dist/line-guided/cv-ops.js +759 -0
  69. package/dist/line-guided/pixeloe-entry.d.ts +15 -0
  70. package/dist/line-guided/pixeloe-entry.js +122 -0
  71. package/dist/line-guided/pixeloe-legacy.d.ts +31 -0
  72. package/dist/line-guided/pixeloe-legacy.js +301 -0
  73. package/dist/line-guided/xdog.d.ts +7 -0
  74. package/dist/line-guided/xdog.js +84 -0
  75. package/dist/most-frequent.d.ts +3 -0
  76. package/dist/most-frequent.js +56 -0
  77. package/dist/outline-prepass.d.ts +37 -0
  78. package/dist/outline-prepass.js +56 -0
  79. package/dist/palette-snap.d.ts +4 -0
  80. package/dist/palette-snap.js +371 -0
  81. package/dist/palette.d.ts +21 -0
  82. package/dist/palette.js +280 -0
  83. package/dist/pixelate.d.ts +15 -0
  84. package/dist/pixelate.js +214 -0
  85. package/dist/pixelation-algorithm-registry.d.ts +34 -0
  86. package/dist/pixelation-algorithm-registry.js +716 -0
  87. package/dist/pixeloe-prepass.d.ts +12 -0
  88. package/dist/pixeloe-prepass.js +527 -0
  89. package/dist/quantization.d.ts +6 -0
  90. package/dist/quantization.js +145 -0
  91. package/dist/remove-background.d.ts +40 -0
  92. package/dist/remove-background.js +229 -0
  93. package/dist/resize.d.ts +3 -0
  94. package/dist/resize.js +86 -0
  95. package/dist/sampling.d.ts +7 -0
  96. package/dist/sampling.js +301 -0
  97. package/dist/settings.d.ts +36 -0
  98. package/dist/settings.js +181 -0
  99. package/dist/types.d.ts +255 -0
  100. package/dist/types.js +87 -0
  101. package/licenses/PixelOE-Apache-2.0.txt +201 -0
  102. package/licenses/pixel-art-fixer-MIT.txt +21 -0
  103. package/licenses/proper-pixel-art-MIT.txt +21 -0
  104. package/licenses/tensorhead-dithering-MIT.txt +21 -0
  105. package/package.json +62 -4
  106. package/wasm/ac-rl-detect-browser-worker.js +45 -0
  107. package/wasm/ac-rl-detect-worker.mjs +51 -0
  108. package/wasm/pixelfixer_detect.d.ts +65 -0
  109. package/wasm/pixelfixer_detect.js +334 -0
  110. package/wasm/pixelfixer_detect_bg.wasm +0 -0
@@ -0,0 +1,36 @@
1
+ import type { PixelBuffer } from "./base.ts";
2
+ import { PixelationMethod, type PixelGridAnalysis, type PixelationSettings, type PixelateOptions } from "./types.ts";
3
+ export declare const MAX_PIXELATION_SIZE = 512;
4
+ export declare const PIXELATION_SIZES: readonly [16, 32, 64, 128, 256, 512];
5
+ export declare const PIXELATION_METHOD_OPTIONS: readonly [{
6
+ readonly value: PixelationMethod.Structure;
7
+ readonly label: "Preserve edges";
8
+ }, {
9
+ readonly value: PixelationMethod.Dominant;
10
+ readonly label: "Dominant colors";
11
+ }, {
12
+ readonly value: PixelationMethod.MostFrequent;
13
+ readonly label: "Most frequent color";
14
+ }, {
15
+ readonly value: PixelationMethod.Box;
16
+ readonly label: "Box average";
17
+ }, {
18
+ readonly value: PixelationMethod.Nearest;
19
+ readonly label: "Nearest-neighbor";
20
+ }];
21
+ export declare function defaultPixelationSettings(image: Pick<PixelBuffer, "width" | "height">, grid?: PixelGridAnalysis): PixelationSettings;
22
+ export declare function updatePixelationSettings(settings: PixelationSettings, patch: Partial<PixelationSettings>, image: Pick<PixelBuffer, "width" | "height">): PixelationSettings;
23
+ export declare function pixelationSettingsOptions(settings: PixelationSettings, image?: Pick<PixelBuffer, "width" | "height">, detected?: PixelGridAnalysis): PixelateOptions;
24
+ /**
25
+ * What a detected grid means for the settings: a reliable one recovers it, anything else falls back
26
+ * to the plain convert (resize). Shared by the import dialog and the tool pages.
27
+ */
28
+ export declare function applyPixelationGrid(settings: PixelationSettings, grid: PixelGridAnalysis, image: Pick<PixelBuffer, "width" | "height">): PixelationSettings;
29
+ /**
30
+ * The output size for typing one dimension: the other follows the image's aspect ratio. Null when the
31
+ * text is not a usable size.
32
+ */
33
+ export declare function pixelationSizeFromAxis(axis: "width" | "height", value: string, image: Pick<PixelBuffer, "width" | "height">): {
34
+ width: number;
35
+ height: number;
36
+ } | null;
@@ -0,0 +1,181 @@
1
+ import { manualPixelGrid, MAX_GRID_CELL_SIZE } from "./grid.js";
2
+ import { DEFAULT_LINE_GUIDE, DEFAULT_OUTLINE_PREPASS, readOutlinePrepass, } from "./outline-prepass.js";
3
+ import { CellColorPicker, LineGuideMode, OutlinePrepass, PaletteColorMode, PixelationDither, PixelationMethod, PixelationMode, } from "./types.js";
4
+ export const MAX_PIXELATION_SIZE = 512;
5
+ export const PIXELATION_SIZES = [16, 32, 64, 128, 256, MAX_PIXELATION_SIZE];
6
+ export const PIXELATION_METHOD_OPTIONS = [
7
+ { value: PixelationMethod.Structure, label: "Preserve edges" },
8
+ { value: PixelationMethod.Dominant, label: "Dominant colors" },
9
+ { value: PixelationMethod.MostFrequent, label: "Most frequent color" },
10
+ { value: PixelationMethod.Box, label: "Box average" },
11
+ { value: PixelationMethod.Nearest, label: "Nearest-neighbor" },
12
+ ];
13
+ const DEFAULT_PIXELATION_SIZE = 64;
14
+ const DEFAULT_COLORS = 16;
15
+ const MAX_COLORS = 256;
16
+ export function defaultPixelationSettings(image, grid) {
17
+ const scale = Math.min(1, DEFAULT_PIXELATION_SIZE / Math.max(image.width, image.height));
18
+ const mode = grid?.reliable ? PixelationMode.RecoverGrid : PixelationMode.Convert;
19
+ // Recover Grid opens on PixelOE + lines with TwoStage and Limit colors (16). Convert opens on
20
+ // PixelOE + lines with Contrast and no color limit. Both use PixelOE's outline pre-pass.
21
+ return {
22
+ mode,
23
+ reduceColors: mode === PixelationMode.RecoverGrid,
24
+ outlineStrength: 0,
25
+ prepass: DEFAULT_OUTLINE_PREPASS,
26
+ lineGuide: DEFAULT_LINE_GUIDE,
27
+ colorPicker: mode === PixelationMode.RecoverGrid ? CellColorPicker.TwoStage : CellColorPicker.Contrast,
28
+ autoGrid: true,
29
+ gridCellWidth: grid?.reliable ? grid.cellWidth : 8,
30
+ gridCellHeight: grid?.reliable ? grid.cellHeight : 8,
31
+ targetWidth: Math.max(1, Math.round(image.width * scale)),
32
+ targetHeight: Math.max(1, Math.round(image.height * scale)),
33
+ maxColors: DEFAULT_COLORS,
34
+ method: PixelationMethod.Structure,
35
+ blockPicker: false,
36
+ preserveDimensions: false,
37
+ removeNoise: false,
38
+ lockAspectRatio: true,
39
+ dither: PixelationDither.None,
40
+ paletteColorMode: PaletteColorMode.Fixed,
41
+ palette: null,
42
+ paletteName: "",
43
+ };
44
+ }
45
+ export function updatePixelationSettings(settings, patch, image) {
46
+ const next = { ...settings, ...patch };
47
+ // Settings saved before the pre-pass dropdown carry the old checkbox instead.
48
+ next.prepass = readOutlinePrepass(patch) ?? readOutlinePrepass(settings) ?? OutlinePrepass.None;
49
+ delete next.pixeloePrepass;
50
+ // Settings saved before Limit colors and Snap palette became one control: either one on means
51
+ // Limit colors, counting Limit colors' own count if it was on, else Snap palette's.
52
+ const legacy = { ...settings, ...patch };
53
+ if (legacy.snapPalette !== undefined || legacy.snapColors !== undefined) {
54
+ if (legacy.snapPalette === true && !next.reduceColors) {
55
+ next.reduceColors = true;
56
+ if (typeof legacy.snapColors === "number")
57
+ next.maxColors = legacy.snapColors;
58
+ }
59
+ delete next.snapPalette;
60
+ delete next.snapColors;
61
+ }
62
+ if (!Object.values(PaletteColorMode).includes(next.paletteColorMode))
63
+ next.paletteColorMode = PaletteColorMode.Fixed;
64
+ if (!Object.values(LineGuideMode).includes(next.lineGuide))
65
+ next.lineGuide = DEFAULT_LINE_GUIDE;
66
+ if (!Object.values(PixelationDither).includes(next.dither))
67
+ next.dither = PixelationDither.None;
68
+ // Turning a PixelOE pre-pass on starts from Contrast, PixelOE's own colour rule.
69
+ if (settings.prepass === OutlinePrepass.None &&
70
+ next.prepass !== OutlinePrepass.None &&
71
+ patch.colorPicker === undefined)
72
+ next.colorPicker = CellColorPicker.Contrast;
73
+ if (patch.palette !== undefined) {
74
+ if (patch.palette && (!patch.palette.length || patch.palette.length > MAX_COLORS))
75
+ throw new RangeError("Choose a palette with 1 to 256 colors.");
76
+ next.palette = patch.palette ? patch.palette.map((color) => [...color]) : null;
77
+ if (patch.palette === null)
78
+ next.paletteName = "";
79
+ }
80
+ // Mode-switch defaults: Recover uses Median and limits colours; plain Convert limits only without a pre-pass.
81
+ if (patch.mode !== undefined && patch.mode !== settings.mode) {
82
+ if (patch.reduceColors === undefined) {
83
+ if (patch.mode === PixelationMode.RecoverGrid) {
84
+ next.reduceColors = true;
85
+ }
86
+ else {
87
+ next.reduceColors = next.prepass === OutlinePrepass.None;
88
+ }
89
+ }
90
+ if (patch.colorPicker === undefined && patch.mode === PixelationMode.RecoverGrid) {
91
+ next.colorPicker = CellColorPicker.TwoStage;
92
+ }
93
+ }
94
+ const cellSize = (value) => Number.isFinite(value) ? Math.max(1, Math.min(MAX_GRID_CELL_SIZE, value)) : 8;
95
+ next.gridCellWidth = cellSize(next.gridCellWidth);
96
+ next.gridCellHeight = cellSize(next.gridCellHeight);
97
+ next.outlineStrength = Number.isFinite(next.outlineStrength)
98
+ ? Math.max(0, Math.min(100, Math.round(next.outlineStrength)))
99
+ : 0;
100
+ const dimension = (value) => Number.isFinite(value) ? Math.max(1, Math.min(MAX_PIXELATION_SIZE, Math.round(value))) : 1;
101
+ next.targetWidth = dimension(next.targetWidth);
102
+ next.targetHeight = dimension(next.targetHeight);
103
+ if (next.lockAspectRatio) {
104
+ const fromHeight = patch.targetHeight !== undefined && patch.targetWidth === undefined;
105
+ const width = fromHeight ? (next.targetHeight * image.width) / image.height : next.targetWidth;
106
+ const height = fromHeight ? next.targetHeight : (next.targetWidth * image.height) / image.width;
107
+ const scale = Math.min(1, MAX_PIXELATION_SIZE / Math.max(width, height));
108
+ next.targetWidth = dimension(width * scale);
109
+ next.targetHeight = dimension(height * scale);
110
+ }
111
+ next.maxColors = Number.isFinite(next.maxColors)
112
+ ? Math.max(2, Math.min(MAX_COLORS, Math.round(next.maxColors)))
113
+ : DEFAULT_COLORS;
114
+ return next;
115
+ }
116
+ export function pixelationSettingsOptions(settings, image, detected) {
117
+ let grid;
118
+ if (settings.mode === PixelationMode.RecoverGrid) {
119
+ if (settings.autoGrid) {
120
+ if (!detected?.reliable)
121
+ throw new Error("No consistent pixel grid was detected. Turn off Automatic grid and choose cell sizes.");
122
+ grid = detected;
123
+ }
124
+ else {
125
+ if (!image)
126
+ throw new Error("Open an image before choosing grid cells.");
127
+ grid = manualPixelGrid(image, settings.gridCellWidth, settings.gridCellHeight);
128
+ }
129
+ }
130
+ return {
131
+ mode: settings.mode,
132
+ grid,
133
+ colorPicker: settings.colorPicker,
134
+ outlineStrength: settings.mode === PixelationMode.Convert ? settings.outlineStrength : 0,
135
+ prepass: settings.prepass,
136
+ lineGuide: settings.lineGuide,
137
+ targetWidth: settings.targetWidth,
138
+ targetHeight: settings.targetHeight,
139
+ // Limit colors: k-means to the colour count, adaptive estimation, or the loaded palette.
140
+ paletteSnap: settings.reduceColors
141
+ ? settings.palette
142
+ ? { palette: settings.palette, dither: settings.dither }
143
+ : settings.paletteColorMode === PaletteColorMode.Adaptive
144
+ ? { adaptive: true, dither: settings.dither }
145
+ : { colors: settings.maxColors, dither: settings.dither }
146
+ : undefined,
147
+ method: settings.method,
148
+ // A pre-pass hands its result to the colour rule, so the picker (not `method`) fills each block.
149
+ blockPicker: settings.blockPicker || settings.prepass !== OutlinePrepass.None,
150
+ preserveDimensions: settings.preserveDimensions,
151
+ removeNoise: settings.removeNoise,
152
+ alphaMode: "premultiplied",
153
+ };
154
+ }
155
+ /**
156
+ * What a detected grid means for the settings: a reliable one recovers it, anything else falls back
157
+ * to the plain convert (resize). Shared by the import dialog and the tool pages.
158
+ */
159
+ export function applyPixelationGrid(settings, grid, image) {
160
+ return updatePixelationSettings(settings, grid.reliable
161
+ ? {
162
+ mode: PixelationMode.RecoverGrid,
163
+ autoGrid: true,
164
+ gridCellWidth: grid.cellWidth,
165
+ gridCellHeight: grid.cellHeight,
166
+ }
167
+ : { mode: PixelationMode.Convert }, image);
168
+ }
169
+ /**
170
+ * The output size for typing one dimension: the other follows the image's aspect ratio. Null when the
171
+ * text is not a usable size.
172
+ */
173
+ export function pixelationSizeFromAxis(axis, value, image) {
174
+ const typed = Number.parseInt(value, 10);
175
+ if (!Number.isFinite(typed) || typed < 1)
176
+ return null;
177
+ const { width, height } = image;
178
+ return axis === "width"
179
+ ? { width: typed, height: Math.max(1, Math.round((typed * height) / width)) }
180
+ : { width: Math.max(1, Math.round((typed * width) / height)), height: typed };
181
+ }
@@ -0,0 +1,255 @@
1
+ import type { Rgba } from "./base.ts";
2
+ /** The intentionally conservative result of the image import heuristic. */
3
+ export declare enum PixelArtClassification {
4
+ LikelyPixelArt = "likely-pixel-art",
5
+ LikelyPhoto = "likely-photo",
6
+ Uncertain = "uncertain"
7
+ }
8
+ export interface PixelArtMetrics {
9
+ width: number;
10
+ height: number;
11
+ sampledPixels: number;
12
+ uniqueColors: number;
13
+ uniqueColorsCapped: boolean;
14
+ uniqueColorRatio: number;
15
+ exactNeighborRatio: number;
16
+ nearNeighborRatio: number;
17
+ edgeDensity: number;
18
+ colorEntropy: number;
19
+ transparentRatio: number;
20
+ opaqueRatio: number;
21
+ }
22
+ export interface PixelArtAnalysisOptions {
23
+ /** Apply the user's choice after the heuristic has run. */
24
+ userOverride?: PixelArtClassification | null;
25
+ /** Bound work for very large photographs while retaining deterministic sampling. */
26
+ maxSamplePixels?: number;
27
+ /** Grid detection algorithm; Auto when omitted. */
28
+ algorithm?: PixelationAlgorithm;
29
+ /** Output size for entries that take one (Custom size); ignored by the others. */
30
+ size?: PixelationSize;
31
+ }
32
+ export interface PixelArtAnalysis {
33
+ /** The choice a caller should use, including an explicit user override. */
34
+ classification: PixelArtClassification;
35
+ /** The heuristic's choice before applying a user override. */
36
+ suggestedClassification: PixelArtClassification;
37
+ /** A 0..1 indication of how far the heuristic was from its decision boundary. */
38
+ confidence: number;
39
+ /** Signed score: positive favors pixel art, negative favors a photo. */
40
+ score: number;
41
+ /** Human-readable, deliberately non-authoritative reasons for the suggestion. */
42
+ evidence: readonly string[];
43
+ metrics: PixelArtMetrics;
44
+ userOverride: PixelArtClassification | null;
45
+ overrideApplied: boolean;
46
+ /** This is a heuristic and must never silently replace a user's choice. */
47
+ isHeuristic: true;
48
+ grid: PixelGridAnalysis;
49
+ }
50
+ export declare enum PixelationMethod {
51
+ Nearest = "nearest",
52
+ Box = "box",
53
+ MostFrequent = "most-frequent",
54
+ Dominant = "dominant",
55
+ Structure = "structure",
56
+ TwoStage = "two-stage"
57
+ }
58
+ export declare enum PixelationMode {
59
+ Convert = "convert",
60
+ RecoverGrid = "recover-grid"
61
+ }
62
+ export declare enum PixelationAlgorithm {
63
+ Auto = "auto",
64
+ EdgeGrid = "edge-grid",
65
+ UniformGrid = "uniform-grid",
66
+ /** Auto's single proposers, each on its own; see the registry for which detector each runs. */
67
+ FrameLattice = "frame-lattice",
68
+ PitchLattice = "pitch-lattice",
69
+ ColorPeriod = "color-period",
70
+ BorderRuns = "border-runs",
71
+ EdgeSpacing = "edge-spacing",
72
+ /** The user names the output size; the image is split into that many even blocks. */
73
+ CustomSize = "custom-size",
74
+ Resize = "resize"
75
+ }
76
+ /**
77
+ * The outline pre-pass ahead of the colour rule. PixelOE runs outline expansion + colour match;
78
+ * PixelOE + lines also guides the expansion weight with an XDoG line drawing of the source.
79
+ */
80
+ export declare enum OutlinePrepass {
81
+ None = "none",
82
+ Pixeloe = "pixeloe",
83
+ PixeloeLines = "pixeloe-lines"
84
+ }
85
+ /** Dithering when Limit colors snaps the result to a smaller palette. Off leaves nearest-colour. */
86
+ export declare enum PixelationDither {
87
+ None = "none",
88
+ Ordered = "ordered",
89
+ FloydSteinberg = "floyd-steinberg"
90
+ }
91
+ /** How the max color count is determined when Limit colors is on. */
92
+ export declare enum PaletteColorMode {
93
+ /** User-specified fixed count (e.g. 16). */
94
+ Fixed = "fixed",
95
+ /** One colour per group of near-duplicate shades (Lab ΔE) in the recovered image. */
96
+ Adaptive = "adaptive"
97
+ }
98
+ /** How a line drawing changes PixelOE's outline weight (1 = spread dark, 0 = spread bright). */
99
+ export declare enum LineGuideMode {
100
+ /** max(weight, lines): PixelOE's own weight, plus dark spreading along every line. */
101
+ Union = "union",
102
+ /** weight = lines: dark spreads only along lines, bright everywhere else. */
103
+ Replace = "replace"
104
+ }
105
+ /** How one colour is chosen for each grid cell, independent of how the grid was found. */
106
+ export declare enum CellColorPicker {
107
+ MostCommon = "most-common",
108
+ Average = "average",
109
+ Median = "median",
110
+ KMeans = "k-means",
111
+ Contrast = "contrast",
112
+ Nearest = "nearest",
113
+ Structure = "structure",
114
+ TwoStage = "two-stage",
115
+ DualRtTwoStage = "dual-rt-two-stage"
116
+ }
117
+ export interface PixelGridGeometry {
118
+ width: number;
119
+ height: number;
120
+ cellWidth: number;
121
+ cellHeight: number;
122
+ offsetX: number;
123
+ offsetY: number;
124
+ /** Explicit cell boundaries (pixel indices, first 0, last = image size) for irregular grids. */
125
+ cutsX?: readonly number[];
126
+ cutsY?: readonly number[];
127
+ }
128
+ export declare enum PixelGridSamplingAxis {
129
+ Horizontal = "horizontal",
130
+ Vertical = "vertical"
131
+ }
132
+ /** A piecewise constant inverse displacement: one shift per band and across-axis interval. */
133
+ export interface PixelGridSamplingStage {
134
+ axis: PixelGridSamplingAxis;
135
+ /** Boundaries along the displaced axis, first 0 and last its length. */
136
+ bands: readonly number[];
137
+ /** Boundaries on the other axis, first 0 and last its length. */
138
+ across: readonly number[];
139
+ /** [band][across interval], in whole source pixels. */
140
+ shifts: readonly (readonly number[] | Int32Array)[];
141
+ }
142
+ export interface PixelGridAnalysis extends PixelGridGeometry {
143
+ confidence: number;
144
+ reliable: boolean;
145
+ /** Registry entry that produced this analysis. */
146
+ algorithm?: PixelationAlgorithm;
147
+ /**
148
+ * Degrees the source was rotated to straighten a tilted grid before it was detected. The cuts
149
+ * are measured in that straightened image, so recovery applies the same rotation first.
150
+ */
151
+ rotation?: number;
152
+ /** Local inverse sampling steps in the straightened source, in application order. */
153
+ sampling?: readonly PixelGridSamplingStage[];
154
+ /**
155
+ * The cuts already follow the image's edges one by one (grid-edge-path), so arbitration reads
156
+ * them as placed, without strip shifts or a phase field.
157
+ */
158
+ placed?: boolean;
159
+ }
160
+ export interface PixelationSize {
161
+ width: number;
162
+ height: number;
163
+ }
164
+ /** Limit colors, applied to the pixelated image (see palette-snap.ts). */
165
+ export interface PaletteSnapOptions {
166
+ /** Number of colours to cluster into (k-means); ignored when `palette` or `adaptive` is given. */
167
+ colors?: number;
168
+ /** Estimate color count from the image instead of using a fixed count. */
169
+ adaptive?: boolean;
170
+ /** Snap every visible pixel to its nearest entry (CIE Lab) instead of clustering. */
171
+ palette?: readonly Rgba[];
172
+ /** Ordered / Floyd–Steinberg while snapping; None (nearest) when omitted. */
173
+ dither?: PixelationDither;
174
+ }
175
+ export interface PixelateOptions {
176
+ mode?: PixelationMode;
177
+ algorithm?: PixelationAlgorithm;
178
+ /** Per-cell colour rule when a grid is recovered; MostCommon when omitted. */
179
+ colorPicker?: CellColorPicker;
180
+ grid?: PixelGridGeometry;
181
+ outlineStrength?: number;
182
+ /**
183
+ * Outline pre-pass; None when omitted. With the Contrast picker and no grid recovered from the
184
+ * source (a plain convert or Custom size), a PixelOE pre-pass runs stock PixelOE end to end
185
+ * (contrast downscale + colour match at the output size); otherwise it is an image -> image step
186
+ * before the picker or sampler.
187
+ */
188
+ prepass?: OutlinePrepass;
189
+ /** How the line drawing guides PixelOE + lines; Union when omitted. */
190
+ lineGuide?: LineGuideMode;
191
+ /** Sampling rule used to choose one representative color per output cell. */
192
+ method?: PixelationMethod;
193
+ /** Split the image into even blocks of the target size and let `colorPicker` choose each colour (instead of `method`). */
194
+ blockPicker?: boolean;
195
+ /** The low-resolution dimensions to generate. */
196
+ targetWidth?: number;
197
+ targetHeight?: number;
198
+ targetSize?: PixelationSize;
199
+ /** Choose low-resolution dimensions by grouping this many source pixels. */
200
+ blockSize?: number | PixelationSize;
201
+ /** Nearest-neighbor upscale to the source dimensions after pixelation. */
202
+ preserveDimensions?: boolean;
203
+ /**
204
+ * Limit colors: Lab k-means to a colour count that keeps rare colours, or snapping to a given
205
+ * palette. Alpha stays per pixel. Off when omitted.
206
+ */
207
+ paletteSnap?: PaletteSnapOptions;
208
+ /** Light smoothing of similar neighboring colors on the working grid. */
209
+ removeNoise?: boolean;
210
+ /** Box mode defaults to straight channel means; premultiplied is useful for compositing. */
211
+ alphaMode?: "straight" | "premultiplied";
212
+ }
213
+ export interface PaletteEntry {
214
+ color: Rgba;
215
+ count: number;
216
+ coverage: number;
217
+ }
218
+ export interface ExtractPaletteOptions {
219
+ /** Number of entries to return. Values above 256 are capped. */
220
+ maxColors?: number;
221
+ ignoreTransparent?: boolean;
222
+ }
223
+ /** Shared conversion draft used by import and standalone tools. */
224
+ export interface PixelationSettings {
225
+ mode: PixelationMode;
226
+ /**
227
+ * Limit colors: snap the result to `maxColors` colours (k-means keeping rare colours) or, when
228
+ * one is loaded, to `palette`.
229
+ */
230
+ reduceColors: boolean;
231
+ outlineStrength: number;
232
+ /** Outline pre-pass ahead of the colour rule (see `PixelateOptions.prepass`). */
233
+ prepass: OutlinePrepass;
234
+ /** Line guide of the PixelOE + lines pre-pass. */
235
+ lineGuide: LineGuideMode;
236
+ colorPicker: CellColorPicker;
237
+ autoGrid: boolean;
238
+ gridCellWidth: number;
239
+ gridCellHeight: number;
240
+ targetWidth: number;
241
+ targetHeight: number;
242
+ maxColors: number;
243
+ method: PixelationMethod;
244
+ /** Colour each target-size block with `colorPicker` rather than resampling with `method`. */
245
+ blockPicker: boolean;
246
+ preserveDimensions: boolean;
247
+ removeNoise: boolean;
248
+ lockAspectRatio: boolean;
249
+ /** Dithering for Limit colors; ignored when Limit colors is off. */
250
+ dither: PixelationDither;
251
+ /** How the color count is chosen when Limit colors is on and no palette is loaded. */
252
+ paletteColorMode: PaletteColorMode;
253
+ palette: readonly Rgba[] | null;
254
+ paletteName: string;
255
+ }
package/dist/types.js ADDED
@@ -0,0 +1,87 @@
1
+ /** The intentionally conservative result of the image import heuristic. */
2
+ export var PixelArtClassification;
3
+ (function (PixelArtClassification) {
4
+ PixelArtClassification["LikelyPixelArt"] = "likely-pixel-art";
5
+ PixelArtClassification["LikelyPhoto"] = "likely-photo";
6
+ PixelArtClassification["Uncertain"] = "uncertain";
7
+ })(PixelArtClassification || (PixelArtClassification = {}));
8
+ export var PixelationMethod;
9
+ (function (PixelationMethod) {
10
+ PixelationMethod["Nearest"] = "nearest";
11
+ PixelationMethod["Box"] = "box";
12
+ PixelationMethod["MostFrequent"] = "most-frequent";
13
+ PixelationMethod["Dominant"] = "dominant";
14
+ PixelationMethod["Structure"] = "structure";
15
+ PixelationMethod["TwoStage"] = "two-stage";
16
+ })(PixelationMethod || (PixelationMethod = {}));
17
+ export var PixelationMode;
18
+ (function (PixelationMode) {
19
+ PixelationMode["Convert"] = "convert";
20
+ PixelationMode["RecoverGrid"] = "recover-grid";
21
+ })(PixelationMode || (PixelationMode = {}));
22
+ export var PixelationAlgorithm;
23
+ (function (PixelationAlgorithm) {
24
+ PixelationAlgorithm["Auto"] = "auto";
25
+ PixelationAlgorithm["EdgeGrid"] = "edge-grid";
26
+ PixelationAlgorithm["UniformGrid"] = "uniform-grid";
27
+ /** Auto's single proposers, each on its own; see the registry for which detector each runs. */
28
+ PixelationAlgorithm["FrameLattice"] = "frame-lattice";
29
+ PixelationAlgorithm["PitchLattice"] = "pitch-lattice";
30
+ PixelationAlgorithm["ColorPeriod"] = "color-period";
31
+ PixelationAlgorithm["BorderRuns"] = "border-runs";
32
+ PixelationAlgorithm["EdgeSpacing"] = "edge-spacing";
33
+ /** The user names the output size; the image is split into that many even blocks. */
34
+ PixelationAlgorithm["CustomSize"] = "custom-size";
35
+ PixelationAlgorithm["Resize"] = "resize";
36
+ })(PixelationAlgorithm || (PixelationAlgorithm = {}));
37
+ /**
38
+ * The outline pre-pass ahead of the colour rule. PixelOE runs outline expansion + colour match;
39
+ * PixelOE + lines also guides the expansion weight with an XDoG line drawing of the source.
40
+ */
41
+ export var OutlinePrepass;
42
+ (function (OutlinePrepass) {
43
+ OutlinePrepass["None"] = "none";
44
+ OutlinePrepass["Pixeloe"] = "pixeloe";
45
+ OutlinePrepass["PixeloeLines"] = "pixeloe-lines";
46
+ })(OutlinePrepass || (OutlinePrepass = {}));
47
+ /** Dithering when Limit colors snaps the result to a smaller palette. Off leaves nearest-colour. */
48
+ export var PixelationDither;
49
+ (function (PixelationDither) {
50
+ PixelationDither["None"] = "none";
51
+ PixelationDither["Ordered"] = "ordered";
52
+ PixelationDither["FloydSteinberg"] = "floyd-steinberg";
53
+ })(PixelationDither || (PixelationDither = {}));
54
+ /** How the max color count is determined when Limit colors is on. */
55
+ export var PaletteColorMode;
56
+ (function (PaletteColorMode) {
57
+ /** User-specified fixed count (e.g. 16). */
58
+ PaletteColorMode["Fixed"] = "fixed";
59
+ /** One colour per group of near-duplicate shades (Lab ΔE) in the recovered image. */
60
+ PaletteColorMode["Adaptive"] = "adaptive";
61
+ })(PaletteColorMode || (PaletteColorMode = {}));
62
+ /** How a line drawing changes PixelOE's outline weight (1 = spread dark, 0 = spread bright). */
63
+ export var LineGuideMode;
64
+ (function (LineGuideMode) {
65
+ /** max(weight, lines): PixelOE's own weight, plus dark spreading along every line. */
66
+ LineGuideMode["Union"] = "union";
67
+ /** weight = lines: dark spreads only along lines, bright everywhere else. */
68
+ LineGuideMode["Replace"] = "replace";
69
+ })(LineGuideMode || (LineGuideMode = {}));
70
+ /** How one colour is chosen for each grid cell, independent of how the grid was found. */
71
+ export var CellColorPicker;
72
+ (function (CellColorPicker) {
73
+ CellColorPicker["MostCommon"] = "most-common";
74
+ CellColorPicker["Average"] = "average";
75
+ CellColorPicker["Median"] = "median";
76
+ CellColorPicker["KMeans"] = "k-means";
77
+ CellColorPicker["Contrast"] = "contrast";
78
+ CellColorPicker["Nearest"] = "nearest";
79
+ CellColorPicker["Structure"] = "structure";
80
+ CellColorPicker["TwoStage"] = "two-stage";
81
+ CellColorPicker["DualRtTwoStage"] = "dual-rt-two-stage";
82
+ })(CellColorPicker || (CellColorPicker = {}));
83
+ export var PixelGridSamplingAxis;
84
+ (function (PixelGridSamplingAxis) {
85
+ PixelGridSamplingAxis["Horizontal"] = "horizontal";
86
+ PixelGridSamplingAxis["Vertical"] = "vertical";
87
+ })(PixelGridSamplingAxis || (PixelGridSamplingAxis = {}));