@thi.ng/imago 0.4.0 → 0.5.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/CHANGELOG.md +40 -1
- package/README.md +147 -11
- package/api.d.ts +231 -34
- package/index.d.ts +18 -0
- package/index.js +18 -0
- package/layers/color.d.ts +3 -0
- package/layers/color.js +31 -0
- package/layers/image.d.ts +1 -1
- package/layers/image.js +18 -6
- package/layers/raw.d.ts +3 -0
- package/layers/raw.js +28 -0
- package/layers/svg.d.ts +1 -1
- package/layers/svg.js +17 -4
- package/layers/text.d.ts +1 -1
- package/layers/text.js +16 -14
- package/ops/composite.js +10 -6
- package/ops/crop.js +12 -3
- package/ops/extend.js +1 -1
- package/ops/output.js +7 -4
- package/ops/resize.js +9 -2
- package/ops/rotate.js +4 -1
- package/ops.d.ts +68 -1
- package/ops.js +13 -1
- package/package.json +60 -6
- package/path.d.ts +1 -0
- package/path.js +4 -0
- package/proc.d.ts +2 -3
- package/proc.js +2 -2
- package/units.d.ts +22 -5
- package/units.js +77 -26
package/index.js
CHANGED
|
@@ -3,3 +3,21 @@ export * from "./ops.js";
|
|
|
3
3
|
export * from "./path.js";
|
|
4
4
|
export * from "./proc.js";
|
|
5
5
|
export * from "./units.js";
|
|
6
|
+
export * from "./layers/color.js";
|
|
7
|
+
export * from "./layers/image.js";
|
|
8
|
+
export * from "./layers/raw.js";
|
|
9
|
+
export * from "./layers/svg.js";
|
|
10
|
+
export * from "./layers/text.js";
|
|
11
|
+
export * from "./ops/blur.js";
|
|
12
|
+
export * from "./ops/composite.js";
|
|
13
|
+
export * from "./ops/crop.js";
|
|
14
|
+
export * from "./ops/dither.js";
|
|
15
|
+
export * from "./ops/exif.js";
|
|
16
|
+
export * from "./ops/extend.js";
|
|
17
|
+
export * from "./ops/gamma.js";
|
|
18
|
+
export * from "./ops/grayscale.js";
|
|
19
|
+
export * from "./ops/hsbl.js";
|
|
20
|
+
export * from "./ops/nest.js";
|
|
21
|
+
export * from "./ops/output.js";
|
|
22
|
+
export * from "./ops/resize.js";
|
|
23
|
+
export * from "./ops/rotate.js";
|
package/layers/color.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { coerceColor, computeSize, positionOrGravity } from "../units.js";
|
|
2
|
+
const colorLayerImpl = async (layer, _, ctx) => {
|
|
3
|
+
const {
|
|
4
|
+
type: __,
|
|
5
|
+
bg,
|
|
6
|
+
gravity,
|
|
7
|
+
path,
|
|
8
|
+
pos,
|
|
9
|
+
ref,
|
|
10
|
+
size,
|
|
11
|
+
unit,
|
|
12
|
+
...opts
|
|
13
|
+
} = layer;
|
|
14
|
+
const layerSize = size ? computeSize(size, ctx.size, ref, unit) : ctx.size;
|
|
15
|
+
const $pos = positionOrGravity(layerSize, ctx.size, layer);
|
|
16
|
+
return {
|
|
17
|
+
input: {
|
|
18
|
+
create: {
|
|
19
|
+
width: layerSize[0],
|
|
20
|
+
height: layerSize[1],
|
|
21
|
+
channels: 4,
|
|
22
|
+
background: coerceColor(bg)
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
...$pos,
|
|
26
|
+
...opts
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
colorLayerImpl
|
|
31
|
+
};
|
package/layers/image.d.ts
CHANGED
package/layers/image.js
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
|
+
import { illegalArgs } from "@thi.ng/errors";
|
|
1
2
|
import sharp from "sharp";
|
|
2
3
|
import { computeSize, ensureSize, positionOrGravity } from "../units.js";
|
|
3
|
-
const
|
|
4
|
+
const imageLayerImpl = async (layer, _, ctx) => {
|
|
4
5
|
const {
|
|
5
6
|
type: __,
|
|
7
|
+
buffer,
|
|
6
8
|
gravity,
|
|
7
9
|
path,
|
|
8
10
|
pos,
|
|
11
|
+
ref,
|
|
9
12
|
size,
|
|
10
13
|
unit,
|
|
11
14
|
...opts
|
|
12
15
|
} = layer;
|
|
13
|
-
|
|
16
|
+
if (!(path || buffer))
|
|
17
|
+
illegalArgs("missing image source");
|
|
18
|
+
const input = sharp(path || buffer);
|
|
14
19
|
const meta = await input.metadata();
|
|
15
20
|
let imgSize = [meta.width, meta.height];
|
|
16
|
-
|
|
21
|
+
if (size)
|
|
22
|
+
imgSize = computeSize(size, imgSize, ref, unit);
|
|
23
|
+
const $pos = positionOrGravity(imgSize, ctx.size, layer);
|
|
17
24
|
if (!size)
|
|
18
25
|
return { input: path, ...$pos, ...opts };
|
|
19
26
|
ensureSize(meta);
|
|
20
|
-
|
|
27
|
+
const { data, info } = await input.resize(imgSize[0], imgSize[1], { fit: "fill" }).raw().toBuffer({ resolveWithObject: true });
|
|
21
28
|
return {
|
|
22
|
-
input:
|
|
29
|
+
input: data,
|
|
30
|
+
raw: {
|
|
31
|
+
width: info.width,
|
|
32
|
+
height: info.height,
|
|
33
|
+
channels: info.channels
|
|
34
|
+
},
|
|
23
35
|
...$pos,
|
|
24
36
|
...opts
|
|
25
37
|
};
|
|
26
38
|
};
|
|
27
39
|
export {
|
|
28
|
-
|
|
40
|
+
imageLayerImpl
|
|
29
41
|
};
|
package/layers/raw.d.ts
ADDED
package/layers/raw.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { positionOrGravity } from "../units.js";
|
|
2
|
+
const rawLayerImpl = async (layer, _, ctx) => {
|
|
3
|
+
const {
|
|
4
|
+
type: __,
|
|
5
|
+
buffer,
|
|
6
|
+
channels,
|
|
7
|
+
gravity,
|
|
8
|
+
pos,
|
|
9
|
+
ref,
|
|
10
|
+
size,
|
|
11
|
+
unit,
|
|
12
|
+
...opts
|
|
13
|
+
} = layer;
|
|
14
|
+
const $pos = positionOrGravity(size, ctx.size, layer);
|
|
15
|
+
return {
|
|
16
|
+
input: Buffer.from(buffer.buffer),
|
|
17
|
+
raw: {
|
|
18
|
+
width: size[0],
|
|
19
|
+
height: size[1],
|
|
20
|
+
channels
|
|
21
|
+
},
|
|
22
|
+
...$pos,
|
|
23
|
+
...opts
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
rawLayerImpl
|
|
28
|
+
};
|
package/layers/svg.d.ts
CHANGED
package/layers/svg.js
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { readText } from "@thi.ng/file-io";
|
|
2
2
|
import { positionOrGravity } from "../units.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { illegalArgs } from "@thi.ng/errors";
|
|
4
|
+
const svgLayerImpl = async (layer, _, ctx) => {
|
|
5
|
+
let {
|
|
6
|
+
type: __,
|
|
7
|
+
body,
|
|
8
|
+
gravity,
|
|
9
|
+
origin,
|
|
10
|
+
path,
|
|
11
|
+
pos,
|
|
12
|
+
ref,
|
|
13
|
+
unit,
|
|
14
|
+
...opts
|
|
15
|
+
} = layer;
|
|
5
16
|
if (path)
|
|
6
17
|
body = readText(path, ctx.logger);
|
|
18
|
+
if (!body)
|
|
19
|
+
illegalArgs("missing SVG doc");
|
|
7
20
|
const w = +(/width="(\d+)"/.exec(body)?.[1] || 0);
|
|
8
21
|
const h = +(/height="(\d+)"/.exec(body)?.[1] || 0);
|
|
9
22
|
return {
|
|
10
23
|
input: Buffer.from(body),
|
|
11
|
-
...positionOrGravity(
|
|
24
|
+
...positionOrGravity([w, h], ctx.size, layer),
|
|
12
25
|
...opts
|
|
13
26
|
};
|
|
14
27
|
};
|
|
15
28
|
export {
|
|
16
|
-
|
|
29
|
+
svgLayerImpl
|
|
17
30
|
};
|
package/layers/text.d.ts
CHANGED
package/layers/text.js
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
import { isFunction } from "@thi.ng/checks";
|
|
2
|
-
import { writeText } from "@thi.ng/file-io";
|
|
3
2
|
import { XML_SVG } from "@thi.ng/prefixes";
|
|
4
|
-
import { computeSize, positionOrGravity } from "../units.js";
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { computeSize, gravityFlags, positionOrGravity } from "../units.js";
|
|
4
|
+
import { readText } from "@thi.ng/file-io";
|
|
5
|
+
const textLayerImpl = async (layer, _, ctx) => {
|
|
6
|
+
let {
|
|
7
7
|
type: __,
|
|
8
|
-
bg = "
|
|
9
|
-
|
|
8
|
+
bg = "#0000",
|
|
9
|
+
body = "",
|
|
10
|
+
color = "#fff",
|
|
10
11
|
font = "sans-serif",
|
|
11
12
|
fontSize = 16,
|
|
12
13
|
padding = 0,
|
|
13
14
|
textGravity = "c",
|
|
14
|
-
body,
|
|
15
15
|
gravity,
|
|
16
|
+
origin,
|
|
16
17
|
path,
|
|
17
18
|
pos,
|
|
19
|
+
ref,
|
|
18
20
|
size,
|
|
19
21
|
unit,
|
|
20
22
|
...opts
|
|
21
23
|
} = layer;
|
|
22
|
-
|
|
23
|
-
const [
|
|
24
|
-
|
|
25
|
-
);
|
|
24
|
+
let bounds;
|
|
25
|
+
const [w, h] = bounds = computeSize(size, ctx.size, ref, unit);
|
|
26
|
+
const [isE, isW, isN, isS] = gravityFlags(textGravity);
|
|
26
27
|
const x = isW ? padding : isE ? w - padding : w / 2;
|
|
27
28
|
const y = isN ? padding : isS ? h - padding : h / 2;
|
|
28
29
|
const align = isW ? "start" : isE ? "end" : "middle";
|
|
29
30
|
const valign = isN ? 0.75 : isS ? 0 : 0.25;
|
|
31
|
+
if (path)
|
|
32
|
+
body = readText(path, ctx.logger);
|
|
30
33
|
const $body = isFunction(body) ? body(ctx) : body;
|
|
31
34
|
const svg = [
|
|
32
35
|
`<svg xmlns="${XML_SVG}" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">`,
|
|
@@ -34,13 +37,12 @@ const textLayer = async (layer, _, ctx) => {
|
|
|
34
37
|
`<text x="${x}" y="${y}" text-anchor="${align}" dy="${valign}em" fill="${color}" font-family="${font}" font-size="${fontSize}">${$body}</text>`,
|
|
35
38
|
`</svg>`
|
|
36
39
|
].join("");
|
|
37
|
-
writeText("text-debug.svg", svg);
|
|
38
40
|
return {
|
|
39
41
|
input: Buffer.from(svg),
|
|
40
|
-
...positionOrGravity(
|
|
42
|
+
...positionOrGravity(bounds, ctx.size, layer),
|
|
41
43
|
...opts
|
|
42
44
|
};
|
|
43
45
|
};
|
|
44
46
|
export {
|
|
45
|
-
|
|
47
|
+
textLayerImpl
|
|
46
48
|
};
|
package/ops/composite.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { defmulti } from "@thi.ng/defmulti";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { colorLayerImpl } from "../layers/color.js";
|
|
3
|
+
import { imageLayerImpl } from "../layers/image.js";
|
|
4
|
+
import { rawLayerImpl } from "../layers/raw.js";
|
|
5
|
+
import { svgLayerImpl } from "../layers/svg.js";
|
|
6
|
+
import { textLayerImpl } from "../layers/text.js";
|
|
5
7
|
const compositeProc = async (spec, input, ctx) => {
|
|
6
8
|
const { layers } = spec;
|
|
7
9
|
const layerSpecs = await Promise.all(
|
|
@@ -14,9 +16,11 @@ const defLayer = defmulti(
|
|
|
14
16
|
(x) => x.type,
|
|
15
17
|
{},
|
|
16
18
|
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
color: colorLayerImpl,
|
|
20
|
+
img: imageLayerImpl,
|
|
21
|
+
raw: rawLayerImpl,
|
|
22
|
+
svg: svgLayerImpl,
|
|
23
|
+
text: textLayerImpl
|
|
20
24
|
}
|
|
21
25
|
);
|
|
22
26
|
export {
|
package/ops/crop.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { isNumber } from "@thi.ng/checks";
|
|
1
2
|
import { illegalArgs } from "@thi.ng/errors";
|
|
2
3
|
import {
|
|
3
4
|
computeMargins,
|
|
4
5
|
computeSize,
|
|
6
|
+
computeSizeWithAspect,
|
|
5
7
|
gravityPosition,
|
|
6
8
|
positionOrGravity
|
|
7
9
|
} from "../units.js";
|
|
8
10
|
const cropProc = async (spec, input, ctx) => {
|
|
9
|
-
const { border, gravity, pos, size, ref, unit } = spec;
|
|
11
|
+
const { aspect, border, gravity, pos, size, ref, unit } = spec;
|
|
10
12
|
if (border == null && size == null)
|
|
11
13
|
illegalArgs("require `border` or `size` option");
|
|
12
14
|
if (border != null) {
|
|
@@ -22,10 +24,17 @@ const cropProc = async (spec, input, ctx) => {
|
|
|
22
24
|
true
|
|
23
25
|
];
|
|
24
26
|
}
|
|
25
|
-
|
|
27
|
+
let $size;
|
|
28
|
+
if (aspect != void 0) {
|
|
29
|
+
if (!isNumber(size))
|
|
30
|
+
illegalArgs("size must be numeric if aspect is used");
|
|
31
|
+
$size = computeSizeWithAspect(size, ctx.size, aspect, unit);
|
|
32
|
+
} else {
|
|
33
|
+
$size = computeSize(size, ctx.size, ref, unit);
|
|
34
|
+
}
|
|
26
35
|
let left = 0, top = 0;
|
|
27
36
|
if (pos) {
|
|
28
|
-
({ left = 0, top = 0 } = positionOrGravity(
|
|
37
|
+
({ left = 0, top = 0 } = positionOrGravity($size, ctx.size, spec) || {});
|
|
29
38
|
} else {
|
|
30
39
|
[left, top] = gravityPosition(gravity || "c", $size, ctx.size);
|
|
31
40
|
}
|
package/ops/extend.js
CHANGED
package/ops/output.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { encode } from "@thi.ng/blurhash";
|
|
2
|
+
import { isNumber, isPlainObject } from "@thi.ng/checks";
|
|
2
3
|
import { writeFile, writeJSON } from "@thi.ng/file-io";
|
|
3
4
|
import { join, resolve } from "node:path";
|
|
4
5
|
import { formatPath } from "../path.js";
|
|
5
|
-
import {
|
|
6
|
+
import { illegalArgs } from "@thi.ng/errors";
|
|
6
7
|
const outputProc = async (spec, input, ctx) => {
|
|
7
8
|
const opts = spec;
|
|
8
9
|
const outDir = resolve(ctx.opts.outDir || ".");
|
|
@@ -11,6 +12,8 @@ const outputProc = async (spec, input, ctx) => {
|
|
|
11
12
|
await outputBlurHash(opts, output, ctx);
|
|
12
13
|
return [input, false];
|
|
13
14
|
}
|
|
15
|
+
if (!opts.path)
|
|
16
|
+
illegalArgs("output path missing");
|
|
14
17
|
if (opts.raw) {
|
|
15
18
|
await outputRaw(opts, output, ctx, outDir);
|
|
16
19
|
return [input, false];
|
|
@@ -81,7 +84,7 @@ const outputRaw = async (opts, output, ctx, outDir) => {
|
|
|
81
84
|
const { alpha = false, meta = false } = isPlainObject(opts.raw) ? opts.raw : {};
|
|
82
85
|
if (alpha)
|
|
83
86
|
output = output.ensureAlpha();
|
|
84
|
-
const { data, info } = await output.
|
|
87
|
+
const { data, info } = await output.raw().toBuffer({ resolveWithObject: true });
|
|
85
88
|
const path = join(outDir, formatPath(opts.path, ctx, opts, data));
|
|
86
89
|
writeFile(path, data, null, ctx.logger);
|
|
87
90
|
ctx.outputs[opts.id] = path;
|
|
@@ -97,7 +100,7 @@ const outputRaw = async (opts, output, ctx, outDir) => {
|
|
|
97
100
|
};
|
|
98
101
|
const outputBlurHash = async (opts, output, ctx) => {
|
|
99
102
|
const { data, info } = await output.ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
100
|
-
const detail = opts.blurhash
|
|
103
|
+
const detail = opts.blurhash === true ? 4 : opts.blurhash;
|
|
101
104
|
const [dx, dy] = isNumber(detail) ? [detail, detail] : detail;
|
|
102
105
|
const hash = encode(
|
|
103
106
|
new Uint32Array(data.buffer),
|
|
@@ -106,8 +109,8 @@ const outputBlurHash = async (opts, output, ctx) => {
|
|
|
106
109
|
dx,
|
|
107
110
|
dy
|
|
108
111
|
);
|
|
109
|
-
ctx.outputs[opts.id] = hash;
|
|
110
112
|
ctx.logger.debug("computed blurhash:", hash);
|
|
113
|
+
ctx.outputs[opts.id] = hash;
|
|
111
114
|
};
|
|
112
115
|
export {
|
|
113
116
|
outputProc
|
package/ops/resize.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
import { isNumber } from "@thi.ng/checks";
|
|
1
2
|
import { GRAVITY_POSITION } from "../api.js";
|
|
2
3
|
import { coerceColor, computeSize } from "../units.js";
|
|
3
4
|
const resizeProc = async (spec, input, ctx) => {
|
|
4
|
-
const { bg, filter, fit, gravity, size, unit } = spec;
|
|
5
|
-
const
|
|
5
|
+
const { bg, filter, fit, gravity, ref, size, unit } = spec;
|
|
6
|
+
const aspect = ctx.size[0] / ctx.size[1];
|
|
7
|
+
let $size = size;
|
|
8
|
+
let width, height;
|
|
9
|
+
if (isNumber($size) && unit !== "%") {
|
|
10
|
+
$size = aspect > 1 ? [$size, $size / aspect] : [$size * aspect, $size];
|
|
11
|
+
}
|
|
12
|
+
[width, height] = computeSize($size, ctx.size, ref, unit);
|
|
6
13
|
return [
|
|
7
14
|
input.resize({
|
|
8
15
|
width,
|
package/ops/rotate.js
CHANGED
|
@@ -5,7 +5,10 @@ const rotateProc = async (spec, input, _) => {
|
|
|
5
5
|
input = input.flop();
|
|
6
6
|
if (flipY)
|
|
7
7
|
input = input.flip();
|
|
8
|
-
return [
|
|
8
|
+
return [
|
|
9
|
+
input.rotate(angle, { background: coerceColor(bg || "#0000") }),
|
|
10
|
+
true
|
|
11
|
+
];
|
|
9
12
|
};
|
|
10
13
|
export {
|
|
11
14
|
rotateProc
|
package/ops.d.ts
CHANGED
|
@@ -1,16 +1,83 @@
|
|
|
1
|
-
import type { BlurSpec, CompSpec, CropSpec, DitherSpec, EXIFSpec, ExtendSpec, GammaSpec, GrayscaleSpec, HSBLSpec, NestSpec, OutputSpec, ProcSpec, ResizeSpec, RotateSpec } from "./api.js";
|
|
1
|
+
import type { BlurSpec, ColorLayer, CompLayer, CompSpec, CropSpec, DitherSpec, EXIFSpec, ExtendSpec, GammaSpec, GrayscaleSpec, HSBLSpec, ImgLayer, NestSpec, OutputSpec, ProcSpec, RawLayer, ResizeSpec, RotateSpec, SVGLayer, TextLayer } from "./api.js";
|
|
2
|
+
/** @internal */
|
|
2
3
|
export declare const defSpec: <T extends ProcSpec>(op: T["op"]) => (opts: Omit<T, "op">) => T;
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare const defLayerSpec: <T extends CompLayer>(type: T["type"]) => (opts: Omit<T, "op">) => T;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new {@link BlurSpec} with given opts.
|
|
8
|
+
*/
|
|
3
9
|
export declare const blur: (opts: Omit<BlurSpec, "op">) => BlurSpec;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new {@link CompSpec} with given opts.
|
|
12
|
+
*/
|
|
4
13
|
export declare const composite: (opts: Omit<CompSpec, "op">) => CompSpec;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new {@link ColorLayer} spec with given opts (for use with
|
|
16
|
+
* {@link composite} / {@link CompSpec}).
|
|
17
|
+
*/
|
|
18
|
+
export declare const colorLayer: (opts: Omit<ColorLayer, "op">) => ColorLayer;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new {@link ImgLayer} spec with given opts (for use with
|
|
21
|
+
* {@link composite} / {@link CompSpec}).
|
|
22
|
+
*/
|
|
23
|
+
export declare const imageLayer: (opts: Omit<ImgLayer, "op">) => ImgLayer;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new {@link RawLayer} spec with given opts (for use with
|
|
26
|
+
* {@link composite} / {@link CompSpec}).
|
|
27
|
+
*/
|
|
28
|
+
export declare const rawLayer: (opts: Omit<RawLayer, "op">) => RawLayer;
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new {@link SVGLayer} spec with given opts (for use with
|
|
31
|
+
* {@link composite} / {@link CompSpec}).
|
|
32
|
+
*/
|
|
33
|
+
export declare const svgLayer: (opts: Omit<SVGLayer, "op">) => SVGLayer;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new {@link TextLayer} spec with given opts (for use with
|
|
36
|
+
* {@link composite} / {@link CompSpec}).
|
|
37
|
+
*/
|
|
38
|
+
export declare const textLayer: (opts: Omit<TextLayer, "op">) => TextLayer;
|
|
39
|
+
/**
|
|
40
|
+
* Creates a new {@link CompSpec} with given opts.
|
|
41
|
+
*/
|
|
5
42
|
export declare const crop: (opts: Omit<CropSpec, "op">) => CropSpec;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new {@link DitherSpec} with given opts.
|
|
45
|
+
*/
|
|
6
46
|
export declare const dither: (opts: Omit<DitherSpec, "op">) => DitherSpec;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new {@link EXIFSpec} with given opts.
|
|
49
|
+
*/
|
|
7
50
|
export declare const exif: (opts: Omit<EXIFSpec, "op">) => EXIFSpec;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new {@link ExtendSpec} with given opts.
|
|
53
|
+
*/
|
|
8
54
|
export declare const extend: (opts: Omit<ExtendSpec, "op">) => ExtendSpec;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new {@link GammaSpec} with given opts.
|
|
57
|
+
*/
|
|
9
58
|
export declare const gamma: (opts: Omit<GammaSpec, "op">) => GammaSpec;
|
|
59
|
+
/**
|
|
60
|
+
* Creates a new {@link GrayscaleSpec} with given opts.
|
|
61
|
+
*/
|
|
10
62
|
export declare const grayscale: (opts: Omit<GrayscaleSpec, "op">) => GrayscaleSpec;
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new {@link HSBLSpec} with given opts.
|
|
65
|
+
*/
|
|
11
66
|
export declare const hsbl: (opts: Omit<HSBLSpec, "op">) => HSBLSpec;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new {@link NestSpec} with given opts.
|
|
69
|
+
*/
|
|
12
70
|
export declare const nest: (opts: Omit<NestSpec, "op">) => NestSpec;
|
|
71
|
+
/**
|
|
72
|
+
* Creates a new {@link OutputSpec} with given opts.
|
|
73
|
+
*/
|
|
13
74
|
export declare const output: (opts: Omit<OutputSpec, "op">) => OutputSpec;
|
|
75
|
+
/**
|
|
76
|
+
* Creates a new {@link ResizeSpec} with given opts.
|
|
77
|
+
*/
|
|
14
78
|
export declare const resize: (opts: Omit<ResizeSpec, "op">) => ResizeSpec;
|
|
79
|
+
/**
|
|
80
|
+
* Creates a new {@link RotateSpec} with given opts.
|
|
81
|
+
*/
|
|
15
82
|
export declare const rotate: (opts: Omit<RotateSpec, "op">) => RotateSpec;
|
|
16
83
|
//# sourceMappingURL=ops.d.ts.map
|
package/ops.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
const defSpec = (op) => (opts) => ({ op, ...opts });
|
|
2
|
+
const defLayerSpec = (type) => (opts) => ({ type, ...opts });
|
|
2
3
|
const blur = defSpec("blur");
|
|
3
4
|
const composite = defSpec("composite");
|
|
5
|
+
const colorLayer = defLayerSpec("color");
|
|
6
|
+
const imageLayer = defLayerSpec("img");
|
|
7
|
+
const rawLayer = defLayerSpec("raw");
|
|
8
|
+
const svgLayer = defLayerSpec("svg");
|
|
9
|
+
const textLayer = defLayerSpec("text");
|
|
4
10
|
const crop = defSpec("crop");
|
|
5
11
|
const dither = defSpec("dither");
|
|
6
12
|
const exif = defSpec("exif");
|
|
@@ -14,8 +20,10 @@ const resize = defSpec("resize");
|
|
|
14
20
|
const rotate = defSpec("rotate");
|
|
15
21
|
export {
|
|
16
22
|
blur,
|
|
23
|
+
colorLayer,
|
|
17
24
|
composite,
|
|
18
25
|
crop,
|
|
26
|
+
defLayerSpec,
|
|
19
27
|
defSpec,
|
|
20
28
|
dither,
|
|
21
29
|
exif,
|
|
@@ -23,8 +31,12 @@ export {
|
|
|
23
31
|
gamma,
|
|
24
32
|
grayscale,
|
|
25
33
|
hsbl,
|
|
34
|
+
imageLayer,
|
|
26
35
|
nest,
|
|
27
36
|
output,
|
|
37
|
+
rawLayer,
|
|
28
38
|
resize,
|
|
29
|
-
rotate
|
|
39
|
+
rotate,
|
|
40
|
+
svgLayer,
|
|
41
|
+
textLayer
|
|
30
42
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/imago",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "JSON & API-based declarative and extensible image processing trees/pipelines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -39,19 +39,19 @@
|
|
|
39
39
|
"@thi.ng/associative": "^6.3.43",
|
|
40
40
|
"@thi.ng/blurhash": "^0.1.11",
|
|
41
41
|
"@thi.ng/checks": "^3.5.0",
|
|
42
|
-
"@thi.ng/date": "^2.7.
|
|
42
|
+
"@thi.ng/date": "^2.7.2",
|
|
43
43
|
"@thi.ng/defmulti": "^3.0.26",
|
|
44
44
|
"@thi.ng/errors": "^2.4.18",
|
|
45
45
|
"@thi.ng/file-io": "^1.3.4",
|
|
46
46
|
"@thi.ng/logger": "^3.0.3",
|
|
47
|
-
"@thi.ng/pixel": "^6.1.
|
|
48
|
-
"@thi.ng/pixel-dither": "^1.1.
|
|
47
|
+
"@thi.ng/pixel": "^6.1.13",
|
|
48
|
+
"@thi.ng/pixel-dither": "^1.1.111",
|
|
49
49
|
"@thi.ng/prefixes": "^2.3.10",
|
|
50
50
|
"sharp": "^0.33.2"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@microsoft/api-extractor": "^7.40.1",
|
|
54
|
-
"@thi.ng/vectors": "^7.10.
|
|
54
|
+
"@thi.ng/vectors": "^7.10.13",
|
|
55
55
|
"esbuild": "^0.20.0",
|
|
56
56
|
"rimraf": "^5.0.5",
|
|
57
57
|
"typedoc": "^0.25.7",
|
|
@@ -109,6 +109,60 @@
|
|
|
109
109
|
"./api": {
|
|
110
110
|
"default": "./api.js"
|
|
111
111
|
},
|
|
112
|
+
"./layers/color": {
|
|
113
|
+
"default": "./layers/color.js"
|
|
114
|
+
},
|
|
115
|
+
"./layers/image": {
|
|
116
|
+
"default": "./layers/image.js"
|
|
117
|
+
},
|
|
118
|
+
"./layers/raw": {
|
|
119
|
+
"default": "./layers/raw.js"
|
|
120
|
+
},
|
|
121
|
+
"./layers/svg": {
|
|
122
|
+
"default": "./layers/svg.js"
|
|
123
|
+
},
|
|
124
|
+
"./layers/text": {
|
|
125
|
+
"default": "./layers/text.js"
|
|
126
|
+
},
|
|
127
|
+
"./ops/blur": {
|
|
128
|
+
"default": "./ops/blur.js"
|
|
129
|
+
},
|
|
130
|
+
"./ops/composite": {
|
|
131
|
+
"default": "./ops/composite.js"
|
|
132
|
+
},
|
|
133
|
+
"./ops/crop": {
|
|
134
|
+
"default": "./ops/crop.js"
|
|
135
|
+
},
|
|
136
|
+
"./ops/dither": {
|
|
137
|
+
"default": "./ops/dither.js"
|
|
138
|
+
},
|
|
139
|
+
"./ops/exif": {
|
|
140
|
+
"default": "./ops/exif.js"
|
|
141
|
+
},
|
|
142
|
+
"./ops/extend": {
|
|
143
|
+
"default": "./ops/extend.js"
|
|
144
|
+
},
|
|
145
|
+
"./ops/gamma": {
|
|
146
|
+
"default": "./ops/gamma.js"
|
|
147
|
+
},
|
|
148
|
+
"./ops/grayscale": {
|
|
149
|
+
"default": "./ops/grayscale.js"
|
|
150
|
+
},
|
|
151
|
+
"./ops/hsbl": {
|
|
152
|
+
"default": "./ops/hsbl.js"
|
|
153
|
+
},
|
|
154
|
+
"./ops/nest": {
|
|
155
|
+
"default": "./ops/nest.js"
|
|
156
|
+
},
|
|
157
|
+
"./ops/output": {
|
|
158
|
+
"default": "./ops/output.js"
|
|
159
|
+
},
|
|
160
|
+
"./ops/resize": {
|
|
161
|
+
"default": "./ops/resize.js"
|
|
162
|
+
},
|
|
163
|
+
"./ops/rotate": {
|
|
164
|
+
"default": "./ops/rotate.js"
|
|
165
|
+
},
|
|
112
166
|
"./ops": {
|
|
113
167
|
"default": "./ops.js"
|
|
114
168
|
},
|
|
@@ -126,5 +180,5 @@
|
|
|
126
180
|
"status": "alpha",
|
|
127
181
|
"year": 2024
|
|
128
182
|
},
|
|
129
|
-
"gitHead": "
|
|
183
|
+
"gitHead": "dab0cb468a4c3d968ee1eea4e5dcd8df4889faa6\n"
|
|
130
184
|
}
|
package/path.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { ImgProcCtx, OutputSpec } from "./api.js";
|
|
|
13
13
|
* - sha1/224/256/384/512: truncated hash of output
|
|
14
14
|
* - w: current width
|
|
15
15
|
* - h: current height
|
|
16
|
+
* - aspect: "p" (portrait), "l" (landscape) or "sq" (square)
|
|
16
17
|
* - date: yyyyMMdd
|
|
17
18
|
* - time: HHmmss
|
|
18
19
|
* - year: 4-digit year
|
package/path.js
CHANGED
|
@@ -38,6 +38,10 @@ const formatPath = (path, ctx, spec, buf) => path.replace(/\{(\w+)\}/g, (match,
|
|
|
38
38
|
return String(ctx.size[0]);
|
|
39
39
|
case "h":
|
|
40
40
|
return String(ctx.size[1]);
|
|
41
|
+
case "aspect": {
|
|
42
|
+
const [w, h] = ctx.size;
|
|
43
|
+
return w > h ? "l" : w < h ? "p" : "sq";
|
|
44
|
+
}
|
|
41
45
|
case "date":
|
|
42
46
|
return FMT_yyyyMMdd_ALT(_, true);
|
|
43
47
|
case "time":
|