@bscotch/sprite-source 1.4.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.
Files changed (67) hide show
  1. package/LICENSE.md +29 -0
  2. package/README.md +84 -0
  3. package/dist/SpriteCache.d.ts +67 -0
  4. package/dist/SpriteCache.d.ts.map +1 -0
  5. package/dist/SpriteCache.js +139 -0
  6. package/dist/SpriteCache.js.map +1 -0
  7. package/dist/SpriteCache.schemas.d.ts +74 -0
  8. package/dist/SpriteCache.schemas.d.ts.map +1 -0
  9. package/dist/SpriteCache.schemas.js +51 -0
  10. package/dist/SpriteCache.schemas.js.map +1 -0
  11. package/dist/SpriteDest.actions.d.ts +18 -0
  12. package/dist/SpriteDest.actions.d.ts.map +1 -0
  13. package/dist/SpriteDest.actions.js +163 -0
  14. package/dist/SpriteDest.actions.js.map +1 -0
  15. package/dist/SpriteDest.d.ts +35 -0
  16. package/dist/SpriteDest.d.ts.map +1 -0
  17. package/dist/SpriteDest.js +359 -0
  18. package/dist/SpriteDest.js.map +1 -0
  19. package/dist/SpriteDest.schemas.d.ts +45 -0
  20. package/dist/SpriteDest.schemas.d.ts.map +1 -0
  21. package/dist/SpriteDest.schemas.js +33 -0
  22. package/dist/SpriteDest.schemas.js.map +1 -0
  23. package/dist/SpriteDir.d.ts +39 -0
  24. package/dist/SpriteDir.d.ts.map +1 -0
  25. package/dist/SpriteDir.js +240 -0
  26. package/dist/SpriteDir.js.map +1 -0
  27. package/dist/SpriteFrame.d.ts +36 -0
  28. package/dist/SpriteFrame.d.ts.map +1 -0
  29. package/dist/SpriteFrame.js +225 -0
  30. package/dist/SpriteFrame.js.map +1 -0
  31. package/dist/SpriteSource.d.ts +60 -0
  32. package/dist/SpriteSource.d.ts.map +1 -0
  33. package/dist/SpriteSource.js +153 -0
  34. package/dist/SpriteSource.js.map +1 -0
  35. package/dist/SpriteSource.schemas.d.ts +56 -0
  36. package/dist/SpriteSource.schemas.d.ts.map +1 -0
  37. package/dist/SpriteSource.schemas.js +54 -0
  38. package/dist/SpriteSource.schemas.js.map +1 -0
  39. package/dist/checksum.d.ts +4 -0
  40. package/dist/checksum.d.ts.map +1 -0
  41. package/dist/checksum.js +28 -0
  42. package/dist/checksum.js.map +1 -0
  43. package/dist/cli.d.mts +3 -0
  44. package/dist/cli.d.mts.map +1 -0
  45. package/dist/cli.mjs +113 -0
  46. package/dist/cli.mjs.map +1 -0
  47. package/dist/constants.d.ts +8 -0
  48. package/dist/constants.d.ts.map +1 -0
  49. package/dist/constants.js +10 -0
  50. package/dist/constants.js.map +1 -0
  51. package/dist/index.d.ts +9 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +8 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/safeFs.d.ts +5 -0
  56. package/dist/safeFs.d.ts.map +1 -0
  57. package/dist/safeFs.js +34 -0
  58. package/dist/safeFs.js.map +1 -0
  59. package/dist/types.d.ts +25 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +2 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/utility.d.ts +25 -0
  64. package/dist/utility.d.ts.map +1 -0
  65. package/dist/utility.js +101 -0
  66. package/dist/utility.js.map +1 -0
  67. package/package.json +58 -0
@@ -0,0 +1,240 @@
1
+ import { pathy, statSafe } from '@bscotch/pathy';
2
+ import { Yy } from '@bscotch/yy';
3
+ import { SpriteFrame } from './SpriteFrame.js';
4
+ import { computeFilesChecksum, computeStringChecksum } from './checksum.js';
5
+ import { retryOptions } from './constants.js';
6
+ import { readdirSafe } from './safeFs.js';
7
+ import { SpriteSourceError, assert } from './utility.js';
8
+ export class SpriteDir {
9
+ path;
10
+ logs;
11
+ issues;
12
+ _frames = [];
13
+ _isSpine = false;
14
+ _spinePaths;
15
+ constructor(path, logs, issues) {
16
+ this.path = path;
17
+ this.logs = logs;
18
+ this.issues = issues;
19
+ }
20
+ get isSpine() {
21
+ return this._isSpine;
22
+ }
23
+ get frames() {
24
+ return [...this._frames];
25
+ }
26
+ get spinePaths() {
27
+ assert(this.isSpine, 'Not a spine sprite');
28
+ return { ...this._spinePaths };
29
+ }
30
+ async updateCache(cache) {
31
+ // Do some initial cleanup of the cache
32
+ // Remove the cache if there has been a spine-type-change
33
+ if (cache.info[this.path.relative] &&
34
+ cache.info[this.path.relative].spine !== this.isSpine) {
35
+ delete cache.info[this.path.relative];
36
+ }
37
+ // Initialize the cache if it doesn't exist
38
+ cache.info[this.path.relative] ||= this.isSpine
39
+ ? {
40
+ spine: true,
41
+ changed: 0,
42
+ checksum: '',
43
+ }
44
+ : {
45
+ spine: false,
46
+ frames: {},
47
+ checksum: '',
48
+ };
49
+ const spriteCache = cache.info[this.path.relative];
50
+ const frameWaits = [];
51
+ if (spriteCache.spine) {
52
+ // Handle the spine case
53
+ const pngs = [...this.spinePaths.pngs];
54
+ pngs.sort((a, b) => a.basename.localeCompare(b.basename, 'en-US'));
55
+ const lastChanged = Math.max(...(await Promise.all([
56
+ statSafe(this.spinePaths.atlas, retryOptions).then((s) => s.mtime.getTime(), () => 0),
57
+ statSafe(this.spinePaths.json, retryOptions).then((s) => s.mtime.getTime(), () => 0),
58
+ ...pngs.map((png) => statSafe(png, retryOptions).then((s) => s.mtime.getTime(), () => 0)),
59
+ ])));
60
+ if (lastChanged !== spriteCache.changed || !spriteCache.checksum) {
61
+ spriteCache.changed = lastChanged;
62
+ spriteCache.checksum = await computeFilesChecksum([
63
+ this.spinePaths.atlas.absolute,
64
+ this.spinePaths.json.absolute,
65
+ ...pngs.map((p) => p.absolute),
66
+ ]);
67
+ }
68
+ }
69
+ else {
70
+ // Remove any frames that no longer exist
71
+ const excessFrames = new Set(Object.keys(spriteCache.frames));
72
+ for (const frame of this.frames) {
73
+ excessFrames.delete(frame.path.relative);
74
+ frameWaits.push(frame.updateCache(spriteCache));
75
+ }
76
+ for (const frame of excessFrames) {
77
+ delete spriteCache.frames[frame];
78
+ }
79
+ }
80
+ const frames = await Promise.all(frameWaits);
81
+ if (!spriteCache.spine) {
82
+ // Sort the checksums by checksum since filenames will change between
83
+ // source and dest. Creates a problem if frame *order* changes, so we
84
+ // may need to deal with that later.
85
+ const frameChecksums = frames.map((f) => f.checksum).sort();
86
+ spriteCache.checksum = computeStringChecksum(frameChecksums.join('-'));
87
+ }
88
+ }
89
+ async bleed() {
90
+ if (this.isSpine) {
91
+ return;
92
+ }
93
+ await Promise.all(this.frames.map((frame) => frame.bleed()));
94
+ }
95
+ async crop() {
96
+ if (this.isSpine) {
97
+ return;
98
+ }
99
+ // Get the boundingbox that captures the bounding boxes of
100
+ // all frames.
101
+ const bboxes = await Promise.all(this.frames.map((frame) => frame.getBoundingBox()));
102
+ const bbox = bboxes.slice(1).reduce((bbox, frameBbox) => {
103
+ return {
104
+ left: Math.min(bbox.left, frameBbox.left),
105
+ right: Math.max(bbox.right, frameBbox.right),
106
+ top: Math.min(bbox.top, frameBbox.top),
107
+ bottom: Math.max(bbox.bottom, frameBbox.bottom),
108
+ };
109
+ }, bboxes[0]);
110
+ // Crop all frames to that bounding box
111
+ await Promise.all(this.frames.map((frame) => frame.crop(bbox)));
112
+ }
113
+ async moveTo(newSpriteDir) {
114
+ await newSpriteDir.ensureDirectory();
115
+ if (this.isSpine) {
116
+ const fromTo = [
117
+ [
118
+ this.spinePaths.atlas,
119
+ newSpriteDir.join(this.spinePaths.atlas.basename),
120
+ ],
121
+ [
122
+ this.spinePaths.json,
123
+ newSpriteDir.join(this.spinePaths.json.basename),
124
+ ],
125
+ ...this.spinePaths.pngs.map((png) => [
126
+ png,
127
+ newSpriteDir.join(png.basename),
128
+ ]),
129
+ ];
130
+ await Promise.all(fromTo.map(([from, to]) => from.copy(to).then(() => from.delete({
131
+ ...retryOptions,
132
+ force: true,
133
+ }))));
134
+ this.logs.push(...fromTo.map(([from, to]) => ({
135
+ action: 'moved',
136
+ path: from.absolute,
137
+ to: to.absolute,
138
+ })));
139
+ }
140
+ else {
141
+ const fromTo = this.frames.map((frame) => [
142
+ frame.path,
143
+ newSpriteDir.join(frame.path.basename),
144
+ ]);
145
+ await Promise.all(this.frames.map((frame) => frame.saveTo(newSpriteDir.join(frame.path.basename)).then(() => frame.path.delete({
146
+ ...retryOptions,
147
+ force: true,
148
+ }))));
149
+ this.logs.push(...fromTo.map(([from, to]) => ({
150
+ action: 'moved',
151
+ path: from.absolute,
152
+ to: to.absolute,
153
+ })));
154
+ }
155
+ // Try to delete the folder
156
+ try {
157
+ await this.path.delete({
158
+ recursive: true,
159
+ ...retryOptions,
160
+ force: true,
161
+ });
162
+ }
163
+ catch (err) {
164
+ this.issues.push(new SpriteSourceError(`Could not delete source folder: ${this.path.relative}`, err));
165
+ }
166
+ }
167
+ /**
168
+ * If there are images in this directory, get a `SpriteDir`
169
+ * instance. Else get `undefined`.
170
+ */
171
+ static async from(path, logs = [], issues = []) {
172
+ const files = (await readdirSafe(path.absolute)).map((file) => pathy(file, path.absolute));
173
+ let pngs = files.filter((file) => file.basename.match(/\.png$/i));
174
+ pngs.sort();
175
+ if (pngs.length === 0) {
176
+ return;
177
+ }
178
+ const sprite = new SpriteDir(path, logs, issues);
179
+ const hasAtlas = !!files.find((f) => f.hasExtension('atlas'));
180
+ if (hasAtlas) {
181
+ sprite._isSpine = true;
182
+ // Then it's either a spine export or a spine sprite folder in GameMaker
183
+ // If it's a spine export, all files will be named "{exportName}.*"
184
+ // If it's a GameMaker spine sprite, there will be a "{exportName}.png",
185
+ // but the other files will be named "{GUID}.*". If there are multiple
186
+ // identifiers (due to incomplete cleanup of a previous import), we'll
187
+ // have to open the yy file to determine the correct GUID.
188
+ // 1. See if we have multiple {name}.atlas files. If so, use the yy file (if there is one) to determine the correct GUID.
189
+ const atlasFiles = files.filter((f) => f.hasExtension('atlas'));
190
+ let frameId = atlasFiles[0].name;
191
+ if (atlasFiles.length > 1) {
192
+ const yyFiles = files.filter((f) => f.hasExtension('yy'));
193
+ assert(yyFiles.length === 1, 'Multiple .atlas files found in a single folder. There must be exactly one .yy file in this folder to determine the correct GUID.');
194
+ const yyFile = yyFiles[0];
195
+ const yy = await Yy.read(yyFile.absolute, 'sprites');
196
+ frameId = yy.frames[0]?.name;
197
+ assert(frameId, `No GUID found in yy file. Cannot determine which .atlas file to use for ${path.relative}`);
198
+ }
199
+ // 2. Get the {name}.atlas and {name}.json files
200
+ const skeletonJson = files.find((f) => f.name === frameId && f.hasExtension('json'));
201
+ const skeletonAtlas = files.find((f) => f.name === frameId && f.hasExtension('atlas'));
202
+ assert(skeletonJson, `No .json file found for ${path.relative}/${frameId}`);
203
+ assert(skeletonAtlas, `No .atlas file found for ${path.relative}/${frameId}`);
204
+ // 3. Set the spine paths. There can be multiple PNGs, and in the case
205
+ // of GameMaker assets there can be *other* PNGs (like thumbnails).
206
+ // So we need to read the atlas file to determine which PNGs are
207
+ // the ones we want.
208
+ const atlasContent = (await skeletonAtlas.read({
209
+ encoding: 'utf8',
210
+ }));
211
+ const pngNames = atlasContent.match(/^.*\.png$/gm);
212
+ pngs = pngs.filter((png) => pngNames?.includes(png.basename));
213
+ assert(pngs.length > 0, 'No PNGs found in atlas file.');
214
+ sprite._spinePaths = {
215
+ atlas: skeletonAtlas,
216
+ json: skeletonJson,
217
+ pngs,
218
+ };
219
+ }
220
+ else {
221
+ sprite._frames = pngs.map((png) => new SpriteFrame(png));
222
+ // Make sure all frames are the same size
223
+ const expectedSize = await sprite.frames[0].getSize();
224
+ for (const frame of sprite.frames.slice(1)) {
225
+ const size = await frame.getSize();
226
+ assert(size.width === expectedSize.width &&
227
+ size.height === expectedSize.height, 'Frames must all be the same size.');
228
+ }
229
+ }
230
+ return sprite;
231
+ }
232
+ toJSON() {
233
+ return {
234
+ path: this.path,
235
+ isSpine: this.isSpine,
236
+ framePaths: this.frames,
237
+ };
238
+ }
239
+ }
240
+ //# sourceMappingURL=SpriteDir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteDir.js","sourceRoot":"","sources":["../src/SpriteDir.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Pathy } from '@bscotch/pathy';
2
+ import { Image } from 'image-js';
3
+ import type { SpriteSummary } from './SpriteCache.schemas.js';
4
+ import type { BBox } from './types.js';
5
+ export declare class SpriteFrame {
6
+ readonly path: Pathy;
7
+ protected _size: undefined | {
8
+ width: number;
9
+ height: number;
10
+ };
11
+ protected _bbox: undefined | BBox;
12
+ protected _image: undefined | Image;
13
+ protected _masks: {
14
+ [minAlpha: string]: Image;
15
+ };
16
+ protected _checksum: undefined | string;
17
+ constructor(path: Pathy);
18
+ protected clearCache(): void;
19
+ updateCache(cache: SpriteSummary): Promise<{
20
+ width: number;
21
+ height: number;
22
+ checksum: string;
23
+ changed: number;
24
+ }>;
25
+ getImage(): Promise<Image>;
26
+ getSize(): Promise<{
27
+ width: number;
28
+ height: number;
29
+ }>;
30
+ getForegroundMask(foregroundMinAlphaFraction?: number): Promise<Image>;
31
+ getBoundingBox(padding?: number): Promise<BBox>;
32
+ crop(bbox: BBox): Promise<void>;
33
+ bleed(): Promise<void>;
34
+ saveTo(path: Pathy): Promise<void>;
35
+ }
36
+ //# sourceMappingURL=SpriteFrame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteFrame.d.ts","sourceRoot":"","sources":["../src/SpriteFrame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAY,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,qBAAa,WAAW;IAOV,QAAQ,CAAC,IAAI,EAAE,KAAK;IANhC,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAAC;IACpC,SAAS,CAAC,MAAM,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAM;IACrD,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAAC;gBAEnB,IAAI,EAAE,KAAK;IAEhC,SAAS,CAAC,UAAU;IAQd,WAAW,CAAC,KAAK,EAAE,aAAa;;;;;;IAkBhC,QAAQ;IASR,OAAO;eA3CyB,MAAM;gBAAU,MAAM;;IAoDtD,iBAAiB,CAAC,0BAA0B,CAAC,EAAE,MAAM;IAerD,cAAc,CAAC,OAAO,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1C,IAAI,CAAC,IAAI,EAAE,IAAI;IAaf,KAAK;IAmFL,MAAM,CAAC,IAAI,EAAE,KAAK;CAIzB"}
@@ -0,0 +1,225 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { Pathy, statSafe } from '@bscotch/pathy';
3
+ import { sequential } from '@bscotch/utility';
4
+ import { Image } from 'image-js';
5
+ import { retryOptions } from './constants.js';
6
+ import { getPngSize } from './utility.js';
7
+ export class SpriteFrame {
8
+ path;
9
+ _size;
10
+ _bbox;
11
+ _image;
12
+ _masks = {};
13
+ _checksum;
14
+ constructor(path) {
15
+ this.path = path;
16
+ }
17
+ clearCache() {
18
+ this._size = undefined;
19
+ this._bbox = undefined;
20
+ this._image = undefined;
21
+ this._checksum = undefined;
22
+ this._masks = {};
23
+ }
24
+ async updateCache(cache) {
25
+ const lastChanged = (await statSafe(this.path, retryOptions)).mtime.getTime();
26
+ const needsUpdate = (cache.frames[this.path.relative]?.changed || 0) !== lastChanged;
27
+ if (!needsUpdate)
28
+ return cache.frames[this.path.relative];
29
+ const [size] = await Promise.all([this.getSize()]);
30
+ cache.frames[this.path.relative] = {
31
+ changed: lastChanged,
32
+ checksum: '', // To be batch-computed later
33
+ height: size.height,
34
+ width: size.width,
35
+ };
36
+ return cache.frames[this.path.relative];
37
+ }
38
+ async getImage() {
39
+ if (this._image) {
40
+ return this._image;
41
+ }
42
+ this._image = await Image.load(this.path.absolute);
43
+ return this._image;
44
+ }
45
+ async getSize() {
46
+ if (this._size) {
47
+ return { ...this._size };
48
+ }
49
+ this._size = await getPngSize(this.path);
50
+ return this._size;
51
+ }
52
+ async getForegroundMask(foregroundMinAlphaFraction) {
53
+ const alphaKey = `${foregroundMinAlphaFraction}`;
54
+ if (this._masks[alphaKey]) {
55
+ return this._masks[alphaKey];
56
+ }
57
+ const image = await this.getImage();
58
+ const threshold = foregroundMinAlphaFraction || 1 / Math.pow(2, image.bitDepth);
59
+ this._masks[alphaKey] = image
60
+ .getChannel(image.channels - 1)
61
+ .mask({ threshold });
62
+ return this._masks[alphaKey];
63
+ }
64
+ async getBoundingBox(padding = 1) {
65
+ if (this._bbox) {
66
+ return { ...this._bbox };
67
+ }
68
+ const foreground = await this.getForegroundMask();
69
+ let left = Infinity;
70
+ let right = -Infinity;
71
+ let top = Infinity;
72
+ let bottom = -Infinity;
73
+ for (let x = 0; x < foreground.width; x++) {
74
+ for (let y = 0; y < foreground.height; y++) {
75
+ if (foreground.getBitXY(x, y)) {
76
+ left = Math.min(left, x);
77
+ right = Math.max(right, x);
78
+ top = Math.min(top, y);
79
+ bottom = Math.max(bottom, y);
80
+ }
81
+ }
82
+ }
83
+ padding = Math.round(padding);
84
+ if (padding > 0) {
85
+ top = Math.max(top - padding, 0);
86
+ left = Math.max(left - padding, 0);
87
+ right = Math.min(right + padding, foreground.width - 1);
88
+ bottom = Math.min(bottom + padding, foreground.height - 1);
89
+ }
90
+ this._bbox = {
91
+ left: left == Infinity ? 0 : left,
92
+ right: right == -Infinity ? foreground.width - 1 : right,
93
+ top: top == Infinity ? 0 : top,
94
+ bottom: bottom == -Infinity ? foreground.height - 1 : bottom,
95
+ };
96
+ return { ...this._bbox };
97
+ }
98
+ async crop(bbox) {
99
+ const img = await this.getImage();
100
+ const cropBox = {
101
+ x: bbox.left,
102
+ y: bbox.top,
103
+ width: bbox.right - bbox.left + 1,
104
+ height: bbox.bottom - bbox.top + 1,
105
+ };
106
+ this.clearCache();
107
+ this._image = img.crop(cropBox);
108
+ }
109
+ async bleed() {
110
+ const img = await this.getImage();
111
+ if (!img.alpha) {
112
+ return;
113
+ }
114
+ const maxPixelValue = Math.pow(2, img.bitDepth);
115
+ const bleedMaxAlpha = Math.ceil(0.02 * maxPixelValue);
116
+ const transparentBlackPixel = [...Array(img.channels)].map(() => 0);
117
+ // Create a mask from the background (alpha zero) and then erode it by a few pixels.
118
+ // Add a mask from the foreground (alpha > 0)
119
+ // Invert to get the background pixels that need to be adjusted
120
+ // Set the color of those pixels to the the color of the nearest foreground, and the alpha
121
+ // to something very low so that it mostly isn't visible but won't be treated as background downstream
122
+ const foreground = await this.getForegroundMask((bleedMaxAlpha + 1) / maxPixelValue);
123
+ const expandedForeground = foreground.dilate({
124
+ kernel: [
125
+ [1, 1, 1],
126
+ [1, 1, 1],
127
+ [1, 1, 1],
128
+ ],
129
+ });
130
+ const isInForeground = (x, y) => foreground.getBitXY(x, y);
131
+ const isInExpandedForeground = (x, y) => expandedForeground.getBitXY(x, y);
132
+ const isInOutline = (x, y) => isInExpandedForeground(x, y) && !isInForeground(x, y);
133
+ // There does not seem to be a way to combine masks in image-js,
134
+ // but we don't really need to for the desired outcome.
135
+ // Iterate over all pixels. Those in the expanded foreground but not in the foreground
136
+ // should be set in the original image based on nearby non-background pixels
137
+ for (let x = 0; x < img.width; x++) {
138
+ for (let y = 0; y < img.height; y++) {
139
+ if (isInOutline(x, y)) {
140
+ const neighbors = [];
141
+ for (let ax = x - 1; ax <= x + 1; ax++) {
142
+ for (let ay = y - 1; ay <= y + 1; ay++) {
143
+ if (ax == x && ay == y) {
144
+ continue;
145
+ }
146
+ if (isInForeground(ax, ay)) {
147
+ neighbors.push(img.getPixelXY(ax, ay));
148
+ }
149
+ }
150
+ }
151
+ if (neighbors.length) {
152
+ // average the colors
153
+ const colorSamples = transparentBlackPixel.map(() => []);
154
+ for (const neighbor of neighbors) {
155
+ for (let channel = 0; channel < img.channels; channel++) {
156
+ colorSamples[channel].push(neighbor[channel]);
157
+ }
158
+ }
159
+ const newColor = colorSamples.map((sample, idx) => {
160
+ if (idx == img.channels - 1) {
161
+ // Alpha should be 2% or half the min neighboring alpha
162
+ const minAlpha = sample.reduce((min, value) => Math.min(min, value), Infinity);
163
+ return Math.ceil(Math.min(minAlpha * 0.5, bleedMaxAlpha));
164
+ }
165
+ else {
166
+ // Use the average color
167
+ return Math.round(sample.reduce((sum, value) => sum + value, 0) / sample.length);
168
+ }
169
+ });
170
+ img.setPixelXY(x, y, newColor);
171
+ }
172
+ }
173
+ }
174
+ }
175
+ this.clearCache();
176
+ this._image = img;
177
+ }
178
+ async saveTo(path) {
179
+ const image = await this.getImage();
180
+ await image.save(path.absolute);
181
+ }
182
+ }
183
+ __decorate([
184
+ sequential,
185
+ __metadata("design:type", Function),
186
+ __metadata("design:paramtypes", []),
187
+ __metadata("design:returntype", Promise)
188
+ ], SpriteFrame.prototype, "getImage", null);
189
+ __decorate([
190
+ sequential,
191
+ __metadata("design:type", Function),
192
+ __metadata("design:paramtypes", []),
193
+ __metadata("design:returntype", Promise)
194
+ ], SpriteFrame.prototype, "getSize", null);
195
+ __decorate([
196
+ sequential,
197
+ __metadata("design:type", Function),
198
+ __metadata("design:paramtypes", [Number]),
199
+ __metadata("design:returntype", Promise)
200
+ ], SpriteFrame.prototype, "getForegroundMask", null);
201
+ __decorate([
202
+ sequential,
203
+ __metadata("design:type", Function),
204
+ __metadata("design:paramtypes", [Object]),
205
+ __metadata("design:returntype", Promise)
206
+ ], SpriteFrame.prototype, "getBoundingBox", null);
207
+ __decorate([
208
+ sequential,
209
+ __metadata("design:type", Function),
210
+ __metadata("design:paramtypes", [Object]),
211
+ __metadata("design:returntype", Promise)
212
+ ], SpriteFrame.prototype, "crop", null);
213
+ __decorate([
214
+ sequential,
215
+ __metadata("design:type", Function),
216
+ __metadata("design:paramtypes", []),
217
+ __metadata("design:returntype", Promise)
218
+ ], SpriteFrame.prototype, "bleed", null);
219
+ __decorate([
220
+ sequential,
221
+ __metadata("design:type", Function),
222
+ __metadata("design:paramtypes", [Pathy]),
223
+ __metadata("design:returntype", Promise)
224
+ ], SpriteFrame.prototype, "saveTo", null);
225
+ //# sourceMappingURL=SpriteFrame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteFrame.js","sourceRoot":"","sources":["../src/SpriteFrame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { Pathy } from '@bscotch/pathy';
2
+ import { SpriteCache } from './SpriteCache.js';
3
+ import { type SpriteSourceConfig, type SpriteSourceStage } from './SpriteSource.schemas.js';
4
+ export declare class SpriteSource extends SpriteCache {
5
+ get configFile(): Pathy<{
6
+ [x: string]: unknown;
7
+ $schema?: string | undefined;
8
+ staging?: {
9
+ [x: string]: unknown;
10
+ dir: string;
11
+ transforms: {
12
+ [x: string]: unknown;
13
+ include?: string | undefined;
14
+ bleed?: boolean | undefined;
15
+ crop?: boolean | undefined;
16
+ synced?: boolean | undefined;
17
+ renames?: {
18
+ [x: string]: unknown;
19
+ from: string;
20
+ to: string;
21
+ }[] | undefined;
22
+ }[];
23
+ }[] | null | undefined;
24
+ ignore?: string[] | null | undefined;
25
+ }>;
26
+ protected resolveStaged(staging: SpriteSourceStage): Promise<void>;
27
+ loadConfig(overrides?: SpriteSourceConfig): Promise<SpriteSourceConfig>;
28
+ /**
29
+ * Transform any staged sprites and add them to the source,
30
+ * and compute updated sprite info.
31
+ */
32
+ update(
33
+ /** Optionally override config options */
34
+ options?: SpriteSourceConfig): Promise<{
35
+ [x: string]: unknown;
36
+ version: number;
37
+ info: Record<string, {
38
+ [x: string]: unknown;
39
+ spine: false;
40
+ checksum: string;
41
+ frames: Record<string, {
42
+ width: number;
43
+ height: number;
44
+ checksum: string;
45
+ changed: number;
46
+ }>;
47
+ } | {
48
+ [x: string]: unknown;
49
+ spine: true;
50
+ checksum: string;
51
+ changed: number;
52
+ }>;
53
+ $schema?: string | undefined;
54
+ }>;
55
+ /**
56
+ * @param options If specified, creates/overwrites the config file with these options.
57
+ */
58
+ static from(spritesRoot: string | Pathy, options?: SpriteSourceConfig): Promise<SpriteSource>;
59
+ }
60
+ //# sourceMappingURL=SpriteSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteSource.d.ts","sourceRoot":"","sources":["../src/SpriteSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AAUnC,qBAAa,YAAa,SAAQ,WAAW;IAC3C,IAAI,UAAU;;;;;;;;;;;;;;;;;;;;OAIb;cAEe,aAAa,CAAC,OAAO,EAAE,iBAAiB;IA4ElD,UAAU,CACd,SAAS,GAAE,kBAAuB,GACjC,OAAO,CAAC,kBAAkB,CAAC;IAsC9B;;;OAGG;IAEG,MAAM;IACV,yCAAyC;IACzC,OAAO,CAAC,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;;;;IAgB9B;;OAEG;WACU,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,CAAC,EAAE,kBAAkB;CAW5E"}