Skip to content

Commit e0b6de6

Browse files
feat(imago): add support for thi.ng/pixel int buffers as input
- update `processImage()`, update docs - add `isIntBufferLike()` helper - rename `src/units.ts` => `src/utils.ts`
1 parent 73fa739 commit e0b6de6

File tree

14 files changed

+64
-23
lines changed

14 files changed

+64
-23
lines changed

packages/imago/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@
181181
"./proc": {
182182
"default": "./proc.js"
183183
},
184-
"./units": {
185-
"default": "./units.js"
184+
"./utils": {
185+
"default": "./utils.js"
186186
}
187187
},
188188
"thi.ng": {

packages/imago/src/api.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
Keys,
77
Range1_4,
88
TypedArray,
9+
UIntArray,
910
} from "@thi.ng/api";
1011
import type { ILogger } from "@thi.ng/logger";
1112
import type {
@@ -85,6 +86,17 @@ export interface Position {
8586

8687
export type BufferLike = TypedArray | Buffer;
8788

89+
/**
90+
* Simplified interface of thi.ng/pixel `IntBuffer`, only defining parts
91+
* relevant to the conversion for {@link processImage}.
92+
*/
93+
export interface IntBufferLike {
94+
width: number;
95+
height: number;
96+
format: { channels: unknown[] };
97+
data: UIntArray;
98+
}
99+
88100
export type Processor = Fn3<
89101
ProcSpec,
90102
Sharp,

packages/imago/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export * from "./api.js";
33
export * from "./ops.js";
44
export * from "./path.js";
55
export * from "./proc.js";
6-
export * from "./units.js";
6+
export * from "./utils.js";
77

88
export * from "./layers/color.js";
99
export * from "./layers/image.js";

packages/imago/src/layers/color.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import type { ColorLayer, CompLayerFn } from "../api.js";
3-
import { coerceColor, computeSize, positionOrGravity } from "../units.js";
3+
import { coerceColor, computeSize, positionOrGravity } from "../utils.js";
44

55
export const colorLayerImpl: CompLayerFn = async (layer, _, ctx) => {
66
const {

packages/imago/src/layers/image.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { illegalArgs } from "@thi.ng/errors";
33
import sharp from "sharp";
44
import type { CompLayerFn, Dim, ImgLayer } from "../api.js";
5-
import { computeSize, ensureSize, positionOrGravity } from "../units.js";
5+
import { computeSize, ensureSize, positionOrGravity } from "../utils.js";
66

77
export const imageLayerImpl: CompLayerFn = async (layer, _, ctx) => {
88
const {

packages/imago/src/layers/raw.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import type { CompLayerFn, RawLayer } from "../api.js";
3-
import { positionOrGravity } from "../units.js";
3+
import { positionOrGravity } from "../utils.js";
44

55
export const rawLayerImpl: CompLayerFn = async (layer, _, ctx) => {
66
const {

packages/imago/src/layers/svg.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import { readText } from "@thi.ng/file-io";
33
import type { CompLayerFn, SVGLayer } from "../api.js";
4-
import { positionOrGravity } from "../units.js";
4+
import { positionOrGravity } from "../utils.js";
55
import { illegalArgs } from "@thi.ng/errors";
66

77
export const svgLayerImpl: CompLayerFn = async (layer, _, ctx) => {

packages/imago/src/layers/text.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { isFunction } from "@thi.ng/checks";
33
import { XML_SVG } from "@thi.ng/prefixes";
44
import type { CompLayerFn, Dim, TextLayer } from "../api.js";
5-
import { computeSize, gravityFlags, positionOrGravity } from "../units.js";
5+
import { computeSize, gravityFlags, positionOrGravity } from "../utils.js";
66
import { readText } from "@thi.ng/file-io";
77

88
export const textLayerImpl: CompLayerFn = async (layer, _, ctx) => {

packages/imago/src/ops/crop.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
computeSizeWithAspect,
99
gravityPosition,
1010
positionOrGravity,
11-
} from "../units.js";
11+
} from "../utils.js";
1212

1313
export const cropProc: Processor = async (spec, input, ctx) => {
1414
const { aspect, border, gravity, pos, size, ref, unit } = <CropSpec>spec;

packages/imago/src/ops/extend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import type { ExtendSpec, Processor } from "../api.js";
3-
import { coerceColor, computeMargins } from "../units.js";
3+
import { coerceColor, computeMargins } from "../utils.js";
44

55
export const extendProc: Processor = async (spec, input, ctx) => {
66
const { bg, border, mode, ref, unit } = <ExtendSpec>spec;

packages/imago/src/ops/resize.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import { isNumber } from "@thi.ng/checks";
33
import { GRAVITY_POSITION, type Processor, type ResizeSpec } from "../api.js";
4-
import { coerceColor, computeSize } from "../units.js";
4+
import { coerceColor, computeSize } from "../utils.js";
55

66
export const resizeProc: Processor = async (spec, input, ctx) => {
77
const { bg, filter, fit, gravity, ref, size, unit } = <ResizeSpec>spec;

packages/imago/src/ops/rotate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import type { Processor, RotateSpec } from "../api.js";
3-
import { coerceColor } from "../units.js";
3+
import { coerceColor } from "../utils.js";
44

55
export const rotateProc: Processor = async (spec, input, _) => {
66
const { angle, bg, flipX, flipY } = <RotateSpec>spec;

packages/imago/src/proc.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
// SPDX-License-Identifier: Apache-2.0
2+
import type { Range1_4 } from "@thi.ng/api";
23
import { isArrayBufferView, isString } from "@thi.ng/checks";
34
import { defmulti } from "@thi.ng/defmulti";
45
import { createTempFile, deleteFile } from "@thi.ng/file-io";
56
import { ROOT } from "@thi.ng/logger";
67
import sharp, { type Sharp } from "sharp";
7-
import type { BufferLike, ImgProcCtx, ImgProcOpts, ProcSpec } from "./api.js";
8+
import type {
9+
BufferLike,
10+
ImgProcCtx,
11+
ImgProcOpts,
12+
IntBufferLike,
13+
ProcSpec,
14+
} from "./api.js";
815
import { blurProc } from "./ops/blur.js";
916
import { compositeProc } from "./ops/composite.js";
1017
import { cropProc } from "./ops/crop.js";
@@ -19,19 +26,19 @@ import { nestProc } from "./ops/nest.js";
1926
import { outputProc } from "./ops/output.js";
2027
import { resizeProc } from "./ops/resize.js";
2128
import { rotateProc } from "./ops/rotate.js";
22-
import { ensureSize } from "./units.js";
29+
import { ensureSize, isIntBufferLike } from "./utils.js";
2330

2431
// ROOT.set(new ConsoleLogger());
2532
export const LOGGER = ROOT.childLogger("imgproc");
2633

2734
/**
28-
* Main API function. Takes an image input (file path, buffer or existing Sharp
29-
* instance) and applies given processing pipeline specs in sequence. Returns a
30-
* promise of final processed image, input metadata (if any), an environment
31-
* object of arbitrary data (likely produced by custom ops/processors) and an
32-
* object of all written output paths (keyed by each output's
33-
* {@link OutputSpec.id}). The process pipeline can be additionally configured
34-
* via provided options.
35+
* Main API function. Takes an image input (file path, Buffer, ArrayBuffer,
36+
* thi.ng/pixel IntBuffer or an existing Sharp instance) and applies given
37+
* processing pipeline specs in sequence. Returns a promise of final processed
38+
* image, input metadata (if any), an environment object of arbitrary data
39+
* (likely produced by custom ops/processors) and an object of all written
40+
* output paths (keyed by each output's {@link OutputSpec.id}). The process
41+
* pipeline can be additionally configured via provided options.
3542
*
3643
* @remarks
3744
* The `parentCtx` arg is internal use only (nested processors)!
@@ -42,14 +49,22 @@ export const LOGGER = ROOT.childLogger("imgproc");
4249
* @param parentCtx
4350
*/
4451
export const processImage = async (
45-
src: string | BufferLike | ArrayBuffer | Sharp,
52+
src: string | BufferLike | ArrayBuffer | IntBufferLike | Sharp,
4653
specs: ProcSpec[],
4754
opts: Partial<ImgProcOpts> = {},
4855
parentCtx?: ImgProcCtx
4956
) => {
5057
let img =
5158
isString(src) || isArrayBufferView(src)
5259
? sharp(<string | BufferLike>src)
60+
: isIntBufferLike(src)
61+
? sharp(new Uint8Array(src.data.buffer), {
62+
raw: {
63+
width: src.width,
64+
height: src.height,
65+
channels: <Range1_4>src.format.channels.length,
66+
},
67+
})
5368
: <Sharp>src;
5469
const meta = await img.metadata();
5570
ensureSize(meta);

packages/imago/src/units.ts renamed to packages/imago/src/utils.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
// SPDX-License-Identifier: Apache-2.0
22
import type { Maybe } from "@thi.ng/api";
3-
import { isArray, isArrayLike, isNumber, isString } from "@thi.ng/checks";
3+
import {
4+
isArray,
5+
isArrayLike,
6+
isNumber,
7+
isPlainObject,
8+
isString,
9+
isTypedArray,
10+
} from "@thi.ng/checks";
411
import { illegalArgs } from "@thi.ng/errors";
512
import type { Metadata } from "sharp";
613
import {
714
GRAVITY_MAP,
815
type Color,
916
type Dim,
1017
type Gravity,
18+
type IntBufferLike,
1119
type Position,
1220
type Sides,
1321
type Size,
@@ -17,6 +25,12 @@ import {
1725

1826
const round = Math.round;
1927

28+
export const isIntBufferLike = (x: any): x is IntBufferLike =>
29+
isNumber(x.width) &&
30+
isNumber(x.height) &&
31+
isTypedArray(x.data) &&
32+
isPlainObject(x.format);
33+
2034
export const ensureSize = (meta: Metadata) =>
2135
!(isNumber(meta.width) && isNumber(meta.height)) &&
2236
illegalArgs("can't determine image size");

0 commit comments

Comments
 (0)