@awflow/avatar-export 1.0.1 → 1.1.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/README.md +24 -2
- package/dist/animated.d.ts +7 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +17 -2
- package/dist/raster.d.ts +6 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,7 +14,14 @@ Every function returns a `Promise<Uint8Array>`. In Node, Bun and Deno the
|
|
|
14
14
|
wasm loads on first use; nothing to set up.
|
|
15
15
|
|
|
16
16
|
```ts
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
svgToPng,
|
|
19
|
+
toApng,
|
|
20
|
+
toGif,
|
|
21
|
+
toPng,
|
|
22
|
+
toSprite,
|
|
23
|
+
} from '@awflow/avatar-export'
|
|
24
|
+
import { frames } from '@awflow/avatar'
|
|
18
25
|
|
|
19
26
|
// a still PNG, 256 px square by default
|
|
20
27
|
const png = await toPng('Linh', { expression: 'happy' }, { size: 512 })
|
|
@@ -25,6 +32,20 @@ const apng = await toApng('Linh', { reaction: 'hop' }, { fps: 30, seconds: 3 })
|
|
|
25
32
|
// a GIF with one 256-colour palette, transparent where nothing is drawn
|
|
26
33
|
const gif = await toGif('Linh', { frame: 'none', activity: 'done' })
|
|
27
34
|
|
|
35
|
+
// a script: idle, then working from 1 s, a cheer at 3 s, idle again at 4 s
|
|
36
|
+
const story = await toGif('Linh', {
|
|
37
|
+
timeline: [
|
|
38
|
+
{ at: 1, activity: 'working' },
|
|
39
|
+
{ at: 3, reaction: 'celebrate' },
|
|
40
|
+
{ at: 4, activity: 'idle' },
|
|
41
|
+
],
|
|
42
|
+
}, { fps: 25, seconds: 5 })
|
|
43
|
+
|
|
44
|
+
// any SVG string, such as one frame of frames(), at a given width
|
|
45
|
+
const still = await svgToPng(frames('Linh', {}, { fps: 1, seconds: 1 })[0], {
|
|
46
|
+
size: 128,
|
|
47
|
+
})
|
|
48
|
+
|
|
28
49
|
// many avatars on one sheet: 3 columns of 64 px tiles, 4 px apart
|
|
29
50
|
const sheet = await toSprite(['Ada', 'Linh', 'Sam'], {}, {
|
|
30
51
|
size: 64,
|
|
@@ -65,7 +86,8 @@ return at once.
|
|
|
65
86
|
`LIMITS` is
|
|
66
87
|
`{ maxFrames: 600, maxSize: 1024, maxSprite: 400, maxSheet: 16777216 }`, with
|
|
67
88
|
`maxFrames` taken from the core's `FRAME_LIMITS` (1 to 120 fps, up to 60
|
|
68
|
-
seconds). `maxSheet` caps a sprite sheet's area
|
|
89
|
+
seconds). `maxSheet` caps a sprite sheet's area, and an `svgToPng` image's,
|
|
90
|
+
at 4096 by 4096 pixels. A `timeline` holds at most `maxFrames` cues. Frames are `round(fps * seconds)`, checked before anything is
|
|
69
91
|
drawn. A value out of range, or not a finite number, throws a `RangeError`
|
|
70
92
|
that names the limit.
|
|
71
93
|
|
package/dist/animated.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { type AvatarOptions, type Reaction } from '@awflow/avatar';
|
|
1
|
+
import { type AvatarOptions, type Cue, type Reaction } from '@awflow/avatar';
|
|
2
|
+
/**
|
|
3
|
+
* What to animate: any avatar options (a registered `character` included),
|
|
4
|
+
* a `reaction` from the first frame, and a `timeline` of later cues: an
|
|
5
|
+
* activity, an expression or a reaction at a time in seconds.
|
|
6
|
+
*/
|
|
2
7
|
export type AnimatedOptions = AvatarOptions & {
|
|
3
8
|
reaction?: Reaction;
|
|
9
|
+
timeline?: readonly Cue[];
|
|
4
10
|
};
|
|
5
11
|
export type AnimationSettings = {
|
|
6
12
|
/** Side in pixels, 1 to LIMITS.maxSize. Default 256. */
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,14 @@ export type { WasmSource } from './raster.js';
|
|
|
6
6
|
export { init } from './raster.js';
|
|
7
7
|
export type { SpriteSettings } from './sprite.js';
|
|
8
8
|
export { toSprite } from './sprite.js';
|
|
9
|
+
/**
|
|
10
|
+
* Any avatar SVG (one frame of `frames()`, or a sheet of them) as a PNG,
|
|
11
|
+
* `size` pixels wide (default 256, at most LIMITS.maxSize). The height
|
|
12
|
+
* follows the SVG's aspect ratio.
|
|
13
|
+
*/
|
|
14
|
+
export declare function svgToPng(svg: string, o?: {
|
|
15
|
+
size?: number;
|
|
16
|
+
}): Promise<Uint8Array>;
|
|
9
17
|
/** The avatar as a still PNG, `size` pixels square (default 256). */
|
|
10
18
|
export declare function toPng(name: string, opts?: AvatarOptions, o?: {
|
|
11
19
|
size?: number;
|
package/dist/index.js
CHANGED
|
@@ -101,8 +101,13 @@ var options = (size) => ({
|
|
|
101
101
|
fitTo: { mode: "width", value: size },
|
|
102
102
|
font: { loadSystemFonts: false }
|
|
103
103
|
});
|
|
104
|
-
function png(svg, size) {
|
|
104
|
+
function png(svg, size, maxPixels) {
|
|
105
105
|
const resvg = new Resvg(svg, options(size));
|
|
106
|
+
const area = resvg.width > 0 ? size * size * (resvg.height / resvg.width) : 0;
|
|
107
|
+
if (maxPixels !== undefined && area > maxPixels) {
|
|
108
|
+
resvg.free();
|
|
109
|
+
throw new RangeError(`svgToPng(): ${Math.round(area)} pixels is above maxSheet ${maxPixels}`);
|
|
110
|
+
}
|
|
106
111
|
const image = resvg.render();
|
|
107
112
|
try {
|
|
108
113
|
return image.asPng();
|
|
@@ -134,7 +139,9 @@ function rgba(svg, size) {
|
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
// src/animated.ts
|
|
137
|
-
import {
|
|
142
|
+
import {
|
|
143
|
+
frames
|
|
144
|
+
} from "@awflow/avatar";
|
|
138
145
|
import * as gifenc from "gifenc";
|
|
139
146
|
|
|
140
147
|
// src/png.ts
|
|
@@ -392,6 +399,13 @@ async function toSprite(names, opts = {}, o = {}) {
|
|
|
392
399
|
}
|
|
393
400
|
|
|
394
401
|
// src/index.ts
|
|
402
|
+
async function svgToPng(svg, o = {}) {
|
|
403
|
+
const size = checkSize("svgToPng()", o.size);
|
|
404
|
+
if (typeof svg !== "string" || !svg.trimStart().startsWith("<svg"))
|
|
405
|
+
throw new TypeError("svgToPng(): svg must be an SVG string");
|
|
406
|
+
await ensure();
|
|
407
|
+
return png(svg, size, LIMITS.maxSheet);
|
|
408
|
+
}
|
|
395
409
|
async function toPng(name, opts = {}, o = {}) {
|
|
396
410
|
const size = checkSize("toPng()", o.size);
|
|
397
411
|
await ensure();
|
|
@@ -402,6 +416,7 @@ export {
|
|
|
402
416
|
toPng,
|
|
403
417
|
toGif,
|
|
404
418
|
toApng,
|
|
419
|
+
svgToPng,
|
|
405
420
|
init,
|
|
406
421
|
LIMITS,
|
|
407
422
|
DEFAULTS
|
package/dist/raster.d.ts
CHANGED
|
@@ -9,8 +9,12 @@ export type WasmSource = ArrayBuffer | ArrayBufferView | Response | URL | WebAss
|
|
|
9
9
|
export declare function init(wasm?: WasmSource | PromiseLike<WasmSource>): Promise<void>;
|
|
10
10
|
/** The export functions wait on this: init() with no argument when needed. */
|
|
11
11
|
export declare const ensure: () => Promise<void>;
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* One SVG as a PNG, size pixels wide, encoded by resvg. With `maxPixels`,
|
|
14
|
+
* an SVG whose height would take the image past that area is refused before
|
|
15
|
+
* any pixel is drawn.
|
|
16
|
+
*/
|
|
17
|
+
export declare function png(svg: string, size: number, maxPixels?: number): Uint8Array;
|
|
14
18
|
/**
|
|
15
19
|
* One SVG as straight (not premultiplied) RGBA pixels, size by size. resvg
|
|
16
20
|
* hands premultiplied pixels back; they are demultiplied the way its own PNG
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awflow/avatar-export",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"LICENSE"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@awflow/avatar": "^1.0
|
|
24
|
+
"@awflow/avatar": "^1.1.0",
|
|
25
25
|
"@resvg/resvg-wasm": "2.6.2",
|
|
26
26
|
"fflate": "0.8.3",
|
|
27
27
|
"gifenc": "1.0.3"
|