@pixerate/editor 0.238.0 → 0.239.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/dist/chunk-KMPM5JM5.js +936 -0
- package/dist/chunk-S6OT6CTS.cjs +936 -0
- package/dist/gradient/index.cjs +102 -812
- package/dist/gradient/index.d.cts +1 -0
- package/dist/gradient/index.d.ts +1 -0
- package/dist/gradient/index.js +85 -795
- package/dist/gradient/sample.d.cts +69 -0
- package/dist/gradient/sample.d.ts +69 -0
- package/dist/image-editor/index.cjs +48 -1
- package/dist/image-editor/index.js +48 -1
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gradients from sampled colours: `simplifyGradientStops` reduces a noisy run of colours (pixels
|
|
3
|
+
* read along a line from a photo, a paint stroke or a shape) to the few stops that reproduce it
|
|
4
|
+
* within a perceptual tolerance, and `sampleGradientFromLine` reads those colours from any pixel
|
|
5
|
+
* reader and returns a linear gradient.
|
|
6
|
+
*
|
|
7
|
+
* Distances are Euclidean in OKLab (ΔE OK, about 0.02 is a just-noticeable step), against the
|
|
8
|
+
* OKLab interpolation the returned gradients use, so what is measured is what is drawn.
|
|
9
|
+
*/
|
|
10
|
+
import type { Gradient, GradientStop } from './types.cjs';
|
|
11
|
+
export interface SimplifyGradientStopsOptions {
|
|
12
|
+
/** Largest perceptual error left between the samples and the stops, in OKLab ΔE (default 0.06). */
|
|
13
|
+
tolerance?: number;
|
|
14
|
+
/** Fewest stops to return (default 2, at least 2). */
|
|
15
|
+
minStops?: number;
|
|
16
|
+
/** Most stops to return (default 5, at least `minStops`). */
|
|
17
|
+
maxStops?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Samples on each side averaged into each one before fitting, to ignore grain, JPEG noise and
|
|
20
|
+
* brush texture (default 2; 0 fits the raw samples).
|
|
21
|
+
*/
|
|
22
|
+
smoothing?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RawGradientSample {
|
|
25
|
+
/** Position along the line, 0..1. */
|
|
26
|
+
offset: number;
|
|
27
|
+
/** Any CSS colour, or RGBA bytes `[r, g, b, a]` (0..255). */
|
|
28
|
+
color: string | readonly [number, number, number, number];
|
|
29
|
+
}
|
|
30
|
+
export interface SimplifiedGradientStops {
|
|
31
|
+
stops: GradientStop[];
|
|
32
|
+
/** The largest OKLab distance left between a (smoothed) sample and the stops. */
|
|
33
|
+
maxError: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Like `simplifyGradientStops`, with the largest error left. Throws a sentence when the input
|
|
37
|
+
* can't make a gradient (fewer than two readable samples, or options out of range).
|
|
38
|
+
*/
|
|
39
|
+
export declare function fitGradientStops(samples: readonly RawGradientSample[], options?: SimplifyGradientStopsOptions): SimplifiedGradientStops;
|
|
40
|
+
/**
|
|
41
|
+
* Reduces colours sampled along a line (offsets 0..1) to a minimal set of gradient stops. The
|
|
42
|
+
* first and last stops sit at 0 and 1; stops are added where the colour turns most until every
|
|
43
|
+
* sample is within `tolerance` (OKLab ΔE) of the OKLab blend between its stops, or `maxStops` is
|
|
44
|
+
* reached. Samples that can't be read (a bad colour string) are skipped. Throws when fewer than two
|
|
45
|
+
* samples can be read.
|
|
46
|
+
*/
|
|
47
|
+
export declare function simplifyGradientStops(samples: readonly RawGradientSample[], options?: SimplifyGradientStopsOptions): GradientStop[];
|
|
48
|
+
export interface LineSamplingOptions extends SimplifyGradientStopsOptions {
|
|
49
|
+
/** Colours read along the line, ends included (default 32, 2..1024). */
|
|
50
|
+
sampleCount?: number;
|
|
51
|
+
/** Snap the line's angle to multiples of this many degrees (e.g. 15, for Shift), keeping its length. */
|
|
52
|
+
snapStep?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Reads colours along the line from `start` to `end` with `readPixel` (which returns a CSS colour,
|
|
56
|
+
* RGBA bytes, or null where there is nothing to read) and returns a linear gradient (OKLab
|
|
57
|
+
* interpolation) whose angle is the line's (CSS degrees) and whose stops are the simplified
|
|
58
|
+
* colours, offsets measured along the line. Returns null when fewer than two points could be read.
|
|
59
|
+
*/
|
|
60
|
+
export declare function sampleGradientFromLine(readPixel: (point: {
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
}) => string | readonly [number, number, number, number] | null, start: {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
}, end: {
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
}, options?: LineSamplingOptions): Gradient | null;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gradients from sampled colours: `simplifyGradientStops` reduces a noisy run of colours (pixels
|
|
3
|
+
* read along a line from a photo, a paint stroke or a shape) to the few stops that reproduce it
|
|
4
|
+
* within a perceptual tolerance, and `sampleGradientFromLine` reads those colours from any pixel
|
|
5
|
+
* reader and returns a linear gradient.
|
|
6
|
+
*
|
|
7
|
+
* Distances are Euclidean in OKLab (ΔE OK, about 0.02 is a just-noticeable step), against the
|
|
8
|
+
* OKLab interpolation the returned gradients use, so what is measured is what is drawn.
|
|
9
|
+
*/
|
|
10
|
+
import type { Gradient, GradientStop } from './types.js';
|
|
11
|
+
export interface SimplifyGradientStopsOptions {
|
|
12
|
+
/** Largest perceptual error left between the samples and the stops, in OKLab ΔE (default 0.06). */
|
|
13
|
+
tolerance?: number;
|
|
14
|
+
/** Fewest stops to return (default 2, at least 2). */
|
|
15
|
+
minStops?: number;
|
|
16
|
+
/** Most stops to return (default 5, at least `minStops`). */
|
|
17
|
+
maxStops?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Samples on each side averaged into each one before fitting, to ignore grain, JPEG noise and
|
|
20
|
+
* brush texture (default 2; 0 fits the raw samples).
|
|
21
|
+
*/
|
|
22
|
+
smoothing?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RawGradientSample {
|
|
25
|
+
/** Position along the line, 0..1. */
|
|
26
|
+
offset: number;
|
|
27
|
+
/** Any CSS colour, or RGBA bytes `[r, g, b, a]` (0..255). */
|
|
28
|
+
color: string | readonly [number, number, number, number];
|
|
29
|
+
}
|
|
30
|
+
export interface SimplifiedGradientStops {
|
|
31
|
+
stops: GradientStop[];
|
|
32
|
+
/** The largest OKLab distance left between a (smoothed) sample and the stops. */
|
|
33
|
+
maxError: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Like `simplifyGradientStops`, with the largest error left. Throws a sentence when the input
|
|
37
|
+
* can't make a gradient (fewer than two readable samples, or options out of range).
|
|
38
|
+
*/
|
|
39
|
+
export declare function fitGradientStops(samples: readonly RawGradientSample[], options?: SimplifyGradientStopsOptions): SimplifiedGradientStops;
|
|
40
|
+
/**
|
|
41
|
+
* Reduces colours sampled along a line (offsets 0..1) to a minimal set of gradient stops. The
|
|
42
|
+
* first and last stops sit at 0 and 1; stops are added where the colour turns most until every
|
|
43
|
+
* sample is within `tolerance` (OKLab ΔE) of the OKLab blend between its stops, or `maxStops` is
|
|
44
|
+
* reached. Samples that can't be read (a bad colour string) are skipped. Throws when fewer than two
|
|
45
|
+
* samples can be read.
|
|
46
|
+
*/
|
|
47
|
+
export declare function simplifyGradientStops(samples: readonly RawGradientSample[], options?: SimplifyGradientStopsOptions): GradientStop[];
|
|
48
|
+
export interface LineSamplingOptions extends SimplifyGradientStopsOptions {
|
|
49
|
+
/** Colours read along the line, ends included (default 32, 2..1024). */
|
|
50
|
+
sampleCount?: number;
|
|
51
|
+
/** Snap the line's angle to multiples of this many degrees (e.g. 15, for Shift), keeping its length. */
|
|
52
|
+
snapStep?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Reads colours along the line from `start` to `end` with `readPixel` (which returns a CSS colour,
|
|
56
|
+
* RGBA bytes, or null where there is nothing to read) and returns a linear gradient (OKLab
|
|
57
|
+
* interpolation) whose angle is the line's (CSS degrees) and whose stops are the simplified
|
|
58
|
+
* colours, offsets measured along the line. Returns null when fewer than two points could be read.
|
|
59
|
+
*/
|
|
60
|
+
export declare function sampleGradientFromLine(readPixel: (point: {
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
}) => string | readonly [number, number, number, number] | null, start: {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
}, end: {
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
}, options?: LineSamplingOptions): Gradient | null;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15; var _class16; var _class17; var _class18;
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
var _chunkS6OT6CTScjs = require('../chunk-S6OT6CTS.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
4
8
|
|
|
5
9
|
|
|
6
10
|
|
|
@@ -17538,7 +17542,50 @@ function createImagePaintTools(controller) {
|
|
|
17538
17542
|
return { color, foreground: controller.getState().paint.foreground };
|
|
17539
17543
|
}
|
|
17540
17544
|
};
|
|
17541
|
-
|
|
17545
|
+
const sampleGradient = {
|
|
17546
|
+
name: "sample_gradient",
|
|
17547
|
+
title: "Sample a gradient along a line",
|
|
17548
|
+
description: "Reads the composite colours along a line from start to end (document pixels), smooths away grain and fits the fewest gradient stops that reproduce them within tolerance. Changes nothing. Returns a linear gradient (CSS angle of the line, oklab interpolation, stops with offsets along the line), its CSS, and how many points could be read. Pass the gradient to a gradient tool (set_gradient) or its stops as paint (set_paint).",
|
|
17549
|
+
inputSchema: {
|
|
17550
|
+
type: "object",
|
|
17551
|
+
properties: {
|
|
17552
|
+
start: { type: "object", properties: { x: { type: "number", description: "Document x in pixels." }, y: { type: "number", description: "Document y in pixels." } }, required: ["x", "y"], additionalProperties: false, description: "Where the gradient starts (offset 0)." },
|
|
17553
|
+
end: { type: "object", properties: { x: { type: "number", description: "Document x in pixels." }, y: { type: "number", description: "Document y in pixels." } }, required: ["x", "y"], additionalProperties: false, description: "Where it ends (offset 1)." },
|
|
17554
|
+
sampleCount: { type: "integer", minimum: 2, maximum: 1024, description: "Points read along the line, ends included (default 32)." },
|
|
17555
|
+
sampleSize: { type: "integer", minimum: 1, maximum: 101, description: "Square averaged at each point, in pixels (default 3)." },
|
|
17556
|
+
tolerance: { type: "number", exclusiveMinimum: 0, maximum: 1, description: "Largest error left, OKLab \u0394E (default 0.06; 0.02 is a just-noticeable step)." },
|
|
17557
|
+
maxStops: { type: "integer", minimum: 2, maximum: 64, description: "Most stops (default 5)." },
|
|
17558
|
+
snapStep: { type: "number", exclusiveMinimum: 0, maximum: 180, description: "Snap the line to multiples of this many degrees, keeping its length (default no snapping)." }
|
|
17559
|
+
},
|
|
17560
|
+
required: ["start", "end"],
|
|
17561
|
+
additionalProperties: false
|
|
17562
|
+
},
|
|
17563
|
+
annotations: { title: "Sample a gradient along a line", ...READ4 },
|
|
17564
|
+
handler: (args) => {
|
|
17565
|
+
const start = args.start;
|
|
17566
|
+
const end = args.end;
|
|
17567
|
+
const size = _nullishCoalesce(args.sampleSize, () => ( 3));
|
|
17568
|
+
let read = 0;
|
|
17569
|
+
let gradient;
|
|
17570
|
+
try {
|
|
17571
|
+
gradient = _chunkS6OT6CTScjs.sampleGradientFromLine.call(void 0,
|
|
17572
|
+
(p) => {
|
|
17573
|
+
const c = controller.sampleColor(p, { size, setForeground: false });
|
|
17574
|
+
if (c) read++;
|
|
17575
|
+
return c;
|
|
17576
|
+
},
|
|
17577
|
+
start,
|
|
17578
|
+
end,
|
|
17579
|
+
{ sampleCount: args.sampleCount, tolerance: args.tolerance, maxStops: args.maxStops, snapStep: args.snapStep }
|
|
17580
|
+
);
|
|
17581
|
+
} catch (e) {
|
|
17582
|
+
throw new (0, _chunkBBUE3UJLcjs.LayerOperationError)(e.message);
|
|
17583
|
+
}
|
|
17584
|
+
if (!gradient) throw new (0, _chunkBBUE3UJLcjs.LayerOperationError)(`Fewer than two points along the line could be read: it runs outside the canvas or over transparent pixels. Read the canvas size with get_image_info and draw the line across visible pixels.`);
|
|
17585
|
+
return { gradient, css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, gradient), pointsRead: read };
|
|
17586
|
+
}
|
|
17587
|
+
};
|
|
17588
|
+
return [paintStroke, fill, clear, getMixer, loadMixerTool, cleanMixerTool, setPaint, getPaint, sampleColor2, sampleGradient];
|
|
17542
17589
|
}
|
|
17543
17590
|
|
|
17544
17591
|
// src/image-editor/color-tools.ts
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
gradientToCss,
|
|
3
|
+
sampleGradientFromLine
|
|
4
|
+
} from "../chunk-KMPM5JM5.js";
|
|
1
5
|
import {
|
|
2
6
|
bendSegment,
|
|
3
7
|
loadOpenTypeFont,
|
|
@@ -17538,7 +17542,50 @@ function createImagePaintTools(controller) {
|
|
|
17538
17542
|
return { color, foreground: controller.getState().paint.foreground };
|
|
17539
17543
|
}
|
|
17540
17544
|
};
|
|
17541
|
-
|
|
17545
|
+
const sampleGradient = {
|
|
17546
|
+
name: "sample_gradient",
|
|
17547
|
+
title: "Sample a gradient along a line",
|
|
17548
|
+
description: "Reads the composite colours along a line from start to end (document pixels), smooths away grain and fits the fewest gradient stops that reproduce them within tolerance. Changes nothing. Returns a linear gradient (CSS angle of the line, oklab interpolation, stops with offsets along the line), its CSS, and how many points could be read. Pass the gradient to a gradient tool (set_gradient) or its stops as paint (set_paint).",
|
|
17549
|
+
inputSchema: {
|
|
17550
|
+
type: "object",
|
|
17551
|
+
properties: {
|
|
17552
|
+
start: { type: "object", properties: { x: { type: "number", description: "Document x in pixels." }, y: { type: "number", description: "Document y in pixels." } }, required: ["x", "y"], additionalProperties: false, description: "Where the gradient starts (offset 0)." },
|
|
17553
|
+
end: { type: "object", properties: { x: { type: "number", description: "Document x in pixels." }, y: { type: "number", description: "Document y in pixels." } }, required: ["x", "y"], additionalProperties: false, description: "Where it ends (offset 1)." },
|
|
17554
|
+
sampleCount: { type: "integer", minimum: 2, maximum: 1024, description: "Points read along the line, ends included (default 32)." },
|
|
17555
|
+
sampleSize: { type: "integer", minimum: 1, maximum: 101, description: "Square averaged at each point, in pixels (default 3)." },
|
|
17556
|
+
tolerance: { type: "number", exclusiveMinimum: 0, maximum: 1, description: "Largest error left, OKLab \u0394E (default 0.06; 0.02 is a just-noticeable step)." },
|
|
17557
|
+
maxStops: { type: "integer", minimum: 2, maximum: 64, description: "Most stops (default 5)." },
|
|
17558
|
+
snapStep: { type: "number", exclusiveMinimum: 0, maximum: 180, description: "Snap the line to multiples of this many degrees, keeping its length (default no snapping)." }
|
|
17559
|
+
},
|
|
17560
|
+
required: ["start", "end"],
|
|
17561
|
+
additionalProperties: false
|
|
17562
|
+
},
|
|
17563
|
+
annotations: { title: "Sample a gradient along a line", ...READ4 },
|
|
17564
|
+
handler: (args) => {
|
|
17565
|
+
const start = args.start;
|
|
17566
|
+
const end = args.end;
|
|
17567
|
+
const size = args.sampleSize ?? 3;
|
|
17568
|
+
let read = 0;
|
|
17569
|
+
let gradient;
|
|
17570
|
+
try {
|
|
17571
|
+
gradient = sampleGradientFromLine(
|
|
17572
|
+
(p) => {
|
|
17573
|
+
const c = controller.sampleColor(p, { size, setForeground: false });
|
|
17574
|
+
if (c) read++;
|
|
17575
|
+
return c;
|
|
17576
|
+
},
|
|
17577
|
+
start,
|
|
17578
|
+
end,
|
|
17579
|
+
{ sampleCount: args.sampleCount, tolerance: args.tolerance, maxStops: args.maxStops, snapStep: args.snapStep }
|
|
17580
|
+
);
|
|
17581
|
+
} catch (e) {
|
|
17582
|
+
throw new LayerOperationError(e.message);
|
|
17583
|
+
}
|
|
17584
|
+
if (!gradient) throw new LayerOperationError(`Fewer than two points along the line could be read: it runs outside the canvas or over transparent pixels. Read the canvas size with get_image_info and draw the line across visible pixels.`);
|
|
17585
|
+
return { gradient, css: gradientToCss(gradient), pointsRead: read };
|
|
17586
|
+
}
|
|
17587
|
+
};
|
|
17588
|
+
return [paintStroke, fill, clear, getMixer, loadMixerTool, cleanMixerTool, setPaint, getPaint, sampleColor2, sampleGradient];
|
|
17542
17589
|
}
|
|
17543
17590
|
|
|
17544
17591
|
// src/image-editor/color-tools.ts
|