@forgeax/engine-image 0.1.20 → 0.1.21
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 +14 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/pixel-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/pixel-surface.unit.test.d.ts.map +1 -0
- package/dist/decode-image-from-file.mjs +2 -1
- package/dist/decode-image-from-file.mjs.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/hdr-decoder.mjs +2 -1
- package/dist/hdr-decoder.mjs.map +1 -1
- package/dist/image-importer.mjs +2 -1
- package/dist/image-importer.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +317 -32
- package/dist/index.mjs.map +1 -1
- package/dist/parse-image.mjs +2 -1
- package/dist/parse-image.mjs.map +1 -1
- package/dist/pixel-surface.d.ts +53 -0
- package/dist/pixel-surface.d.ts.map +1 -0
- package/package.json +6 -6
- package/src/__tests__/errors.test-d.ts +11 -3
- package/src/__tests__/image-importer-conversion-failure.unit.test.ts +21 -0
- package/src/__tests__/pixel-surface.unit.test.ts +94 -0
- package/src/errors.ts +2 -0
- package/src/index.ts +8 -0
- package/src/pixel-surface.ts +428 -0
package/dist/index.mjs
CHANGED
|
@@ -19,7 +19,8 @@ var IMAGE_ERROR_EXPECTED = {
|
|
|
19
19
|
// .hint after switch (err.code) without parsing the message).
|
|
20
20
|
"atlas-empty-input": "images.length >= 1",
|
|
21
21
|
"atlas-size-exceeded": "image width x height <= maxAtlasSize^2 and each image fits in the atlas footprint",
|
|
22
|
-
"atlas-region-mismatch": "sum(regions[i].w x regions[i].h) <= atlasWidth x atlasHeight"
|
|
22
|
+
"atlas-region-mismatch": "sum(regions[i].w x regions[i].h) <= atlasWidth x atlasHeight",
|
|
23
|
+
"image-surface-invalid": "PixelSurface dimensions and authoring inputs satisfy the RGBA8 contract"
|
|
23
24
|
};
|
|
24
25
|
var ImageErrorImpl = class extends Error {
|
|
25
26
|
code;
|
|
@@ -273,6 +274,314 @@ async function loadJpeg() {
|
|
|
273
274
|
return mod.default ?? mod;
|
|
274
275
|
}
|
|
275
276
|
|
|
277
|
+
// src/to-asset-pack.ts
|
|
278
|
+
function toAssetPack(decoded, meta) {
|
|
279
|
+
return {
|
|
280
|
+
schemaVersion: "1.0.0",
|
|
281
|
+
kind: "external-asset-package",
|
|
282
|
+
importer: "image",
|
|
283
|
+
source: "",
|
|
284
|
+
importSettings: {
|
|
285
|
+
colorSpace: meta.colorSpace,
|
|
286
|
+
mipmap: meta.mipmap,
|
|
287
|
+
addressMode: meta.addressMode,
|
|
288
|
+
filterMode: meta.filterMode,
|
|
289
|
+
...meta.downscaleMaxDimension !== void 0 ? { downscaleMaxDimension: meta.downscaleMaxDimension } : {}
|
|
290
|
+
},
|
|
291
|
+
subAssets: [
|
|
292
|
+
{
|
|
293
|
+
guid: meta.guid,
|
|
294
|
+
sourceIndex: 0,
|
|
295
|
+
kind: "texture"
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// src/pixel-surface.ts
|
|
302
|
+
function invalid(operation, field, value, expected) {
|
|
303
|
+
return err(
|
|
304
|
+
imageError({
|
|
305
|
+
code: "image-surface-invalid",
|
|
306
|
+
operation,
|
|
307
|
+
field,
|
|
308
|
+
value,
|
|
309
|
+
expected
|
|
310
|
+
})
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
function finiteNumber(operation, field, value) {
|
|
314
|
+
if (!Number.isFinite(value)) {
|
|
315
|
+
return invalid(operation, field, String(value), "a finite number");
|
|
316
|
+
}
|
|
317
|
+
return ok(value);
|
|
318
|
+
}
|
|
319
|
+
function positiveDimension(operation, field, value) {
|
|
320
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
321
|
+
return invalid(operation, field, value, "a positive integer");
|
|
322
|
+
}
|
|
323
|
+
return ok(value);
|
|
324
|
+
}
|
|
325
|
+
function colorChannels(operation, color) {
|
|
326
|
+
const channels = Array.isArray(color) ? color : color !== null && typeof color === "object" ? [
|
|
327
|
+
color.r,
|
|
328
|
+
color.g,
|
|
329
|
+
color.b,
|
|
330
|
+
color.a
|
|
331
|
+
] : void 0;
|
|
332
|
+
if (channels === void 0 || channels.length !== 4) {
|
|
333
|
+
return invalid(operation, "color", "malformed", "four finite RGBA8 channels");
|
|
334
|
+
}
|
|
335
|
+
const normalized = [0, 0, 0, 0];
|
|
336
|
+
for (let index = 0; index < channels.length; index += 1) {
|
|
337
|
+
const channel = channels[index];
|
|
338
|
+
if (channel === void 0 || !Number.isFinite(channel) || channel < 0 || channel > 255) {
|
|
339
|
+
return invalid(
|
|
340
|
+
operation,
|
|
341
|
+
`color[${index}]`,
|
|
342
|
+
channel ?? "missing",
|
|
343
|
+
"a finite number in [0, 255]"
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
normalized[index] = Math.round(channel);
|
|
347
|
+
}
|
|
348
|
+
return ok(normalized);
|
|
349
|
+
}
|
|
350
|
+
function rounded(operation, field, value) {
|
|
351
|
+
const result = finiteNumber(operation, field, value);
|
|
352
|
+
return result.ok ? ok(Math.round(result.value)) : result;
|
|
353
|
+
}
|
|
354
|
+
function rectangle(operation, x, y, width, height) {
|
|
355
|
+
const values = [x, y, width, height];
|
|
356
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
357
|
+
const value = values[index];
|
|
358
|
+
if (value === void 0 || !Number.isFinite(value)) {
|
|
359
|
+
return invalid(
|
|
360
|
+
operation,
|
|
361
|
+
["x", "y", "width", "height"][index] ?? "rectangle",
|
|
362
|
+
String(value),
|
|
363
|
+
"a finite number"
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (width <= 0 || height <= 0) {
|
|
368
|
+
return invalid(
|
|
369
|
+
operation,
|
|
370
|
+
width <= 0 ? "width" : "height",
|
|
371
|
+
width <= 0 ? width : height,
|
|
372
|
+
"a positive number"
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
return ok([Math.round(x), Math.round(y), Math.round(width), Math.round(height)]);
|
|
376
|
+
}
|
|
377
|
+
function writePixel(data, width, x, y, color) {
|
|
378
|
+
if (x < 0 || y < 0 || x >= width) return;
|
|
379
|
+
const offset = (y * width + x) * 4;
|
|
380
|
+
data[offset] = color[0] ?? 0;
|
|
381
|
+
data[offset + 1] = color[1] ?? 0;
|
|
382
|
+
data[offset + 2] = color[2] ?? 0;
|
|
383
|
+
data[offset + 3] = color[3] ?? 0;
|
|
384
|
+
}
|
|
385
|
+
function fillClippedRect(data, width, height, x, y, rectWidth, rectHeight, color) {
|
|
386
|
+
const left = Math.max(0, x);
|
|
387
|
+
const top = Math.max(0, y);
|
|
388
|
+
const right = Math.min(width, x + rectWidth);
|
|
389
|
+
const bottom = Math.min(height, y + rectHeight);
|
|
390
|
+
for (let row = top; row < bottom; row += 1) {
|
|
391
|
+
for (let column = left; column < right; column += 1) {
|
|
392
|
+
writePixel(data, width, column, row, color);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function nextRandom(state) {
|
|
397
|
+
let value = state >>> 0;
|
|
398
|
+
value ^= value << 13;
|
|
399
|
+
value ^= value >>> 17;
|
|
400
|
+
value ^= value << 5;
|
|
401
|
+
return value >>> 0;
|
|
402
|
+
}
|
|
403
|
+
function makeSurface(options) {
|
|
404
|
+
const width = positiveDimension("create", "width", options.width);
|
|
405
|
+
if (!width.ok) return width;
|
|
406
|
+
const height = positiveDimension("create", "height", options.height);
|
|
407
|
+
if (!height.ok) return height;
|
|
408
|
+
if (options.colorSpace !== void 0 && options.colorSpace !== "srgb" && options.colorSpace !== "linear") {
|
|
409
|
+
return invalid("create", "colorSpace", String(options.colorSpace), "'srgb' or 'linear'");
|
|
410
|
+
}
|
|
411
|
+
if (options.mipmap !== void 0 && typeof options.mipmap !== "boolean") {
|
|
412
|
+
return invalid("create", "mipmap", String(options.mipmap), "a boolean");
|
|
413
|
+
}
|
|
414
|
+
const data = new Uint8Array(width.value * height.value * 4);
|
|
415
|
+
const colorSpace = options.colorSpace ?? "srgb";
|
|
416
|
+
const mipmap = options.mipmap ?? false;
|
|
417
|
+
const surface = {
|
|
418
|
+
width: width.value,
|
|
419
|
+
height: height.value,
|
|
420
|
+
colorSpace,
|
|
421
|
+
mipmap,
|
|
422
|
+
data,
|
|
423
|
+
setPixel(x, y, color) {
|
|
424
|
+
const px = rounded("set-pixel", "x", x);
|
|
425
|
+
if (!px.ok) return px;
|
|
426
|
+
const py = rounded("set-pixel", "y", y);
|
|
427
|
+
if (!py.ok) return py;
|
|
428
|
+
const normalized = colorChannels("set-pixel", color);
|
|
429
|
+
if (!normalized.ok) return normalized;
|
|
430
|
+
writePixel(data, width.value, px.value, py.value, normalized.value);
|
|
431
|
+
return ok(void 0);
|
|
432
|
+
},
|
|
433
|
+
fillRect(x, y, rectWidth, rectHeight, color) {
|
|
434
|
+
const rect = rectangle("fill-rect", x, y, rectWidth, rectHeight);
|
|
435
|
+
if (!rect.ok) return rect;
|
|
436
|
+
const normalized = colorChannels("fill-rect", color);
|
|
437
|
+
if (!normalized.ok) return normalized;
|
|
438
|
+
fillClippedRect(
|
|
439
|
+
data,
|
|
440
|
+
width.value,
|
|
441
|
+
height.value,
|
|
442
|
+
rect.value[0] ?? 0,
|
|
443
|
+
rect.value[1] ?? 0,
|
|
444
|
+
rect.value[2] ?? 0,
|
|
445
|
+
rect.value[3] ?? 0,
|
|
446
|
+
normalized.value
|
|
447
|
+
);
|
|
448
|
+
return ok(void 0);
|
|
449
|
+
},
|
|
450
|
+
fillCircle(cx, cy, radius, color) {
|
|
451
|
+
const centerX = rounded("fill-circle", "cx", cx);
|
|
452
|
+
if (!centerX.ok) return centerX;
|
|
453
|
+
const centerY = rounded("fill-circle", "cy", cy);
|
|
454
|
+
if (!centerY.ok) return centerY;
|
|
455
|
+
const circleRadius = rounded("fill-circle", "radius", radius);
|
|
456
|
+
if (!circleRadius.ok) return circleRadius;
|
|
457
|
+
if (circleRadius.value <= 0) {
|
|
458
|
+
return invalid("fill-circle", "radius", circleRadius.value, "a positive number");
|
|
459
|
+
}
|
|
460
|
+
const normalized = colorChannels("fill-circle", color);
|
|
461
|
+
if (!normalized.ok) return normalized;
|
|
462
|
+
const radiusSquared = circleRadius.value * circleRadius.value;
|
|
463
|
+
const left = Math.max(0, centerX.value - circleRadius.value);
|
|
464
|
+
const right = Math.min(width.value - 1, centerX.value + circleRadius.value);
|
|
465
|
+
const top = Math.max(0, centerY.value - circleRadius.value);
|
|
466
|
+
const bottom = Math.min(height.value - 1, centerY.value + circleRadius.value);
|
|
467
|
+
for (let row = top; row <= bottom; row += 1) {
|
|
468
|
+
for (let column = left; column <= right; column += 1) {
|
|
469
|
+
const dx = column - centerX.value;
|
|
470
|
+
const dy = row - centerY.value;
|
|
471
|
+
if (dx * dx + dy * dy <= radiusSquared)
|
|
472
|
+
writePixel(data, width.value, column, row, normalized.value);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return ok(void 0);
|
|
476
|
+
},
|
|
477
|
+
blit(source, destinationX, destinationY, sourceRect) {
|
|
478
|
+
const destination = rounded("blit", "destinationX", destinationX);
|
|
479
|
+
if (!destination.ok) return destination;
|
|
480
|
+
const destinationYResult = rounded("blit", "destinationY", destinationY);
|
|
481
|
+
if (!destinationYResult.ok) return destinationYResult;
|
|
482
|
+
if (source === null || typeof source !== "object" || !Number.isInteger(source.width) || !Number.isInteger(source.height) || !(source.data instanceof Uint8Array) || source.data.length !== source.width * source.height * 4) {
|
|
483
|
+
return invalid("blit", "source", "malformed", "a valid PixelSurface");
|
|
484
|
+
}
|
|
485
|
+
const rect = rectangle(
|
|
486
|
+
"blit",
|
|
487
|
+
sourceRect?.x ?? 0,
|
|
488
|
+
sourceRect?.y ?? 0,
|
|
489
|
+
sourceRect?.width ?? source.width,
|
|
490
|
+
sourceRect?.height ?? source.height
|
|
491
|
+
);
|
|
492
|
+
if (!rect.ok) return rect;
|
|
493
|
+
const sourceX = rect.value[0] ?? 0;
|
|
494
|
+
const sourceY = rect.value[1] ?? 0;
|
|
495
|
+
const sourceWidth = rect.value[2] ?? 0;
|
|
496
|
+
const sourceHeight = rect.value[3] ?? 0;
|
|
497
|
+
const left = Math.max(0, sourceX);
|
|
498
|
+
const top = Math.max(0, sourceY);
|
|
499
|
+
const right = Math.min(source.width, sourceX + sourceWidth);
|
|
500
|
+
const bottom = Math.min(source.height, sourceY + sourceHeight);
|
|
501
|
+
if (right <= left || bottom <= top) return ok(void 0);
|
|
502
|
+
const snapshot = source.data.slice();
|
|
503
|
+
for (let row = top; row < bottom; row += 1) {
|
|
504
|
+
for (let column = left; column < right; column += 1) {
|
|
505
|
+
const targetX = destination.value + column - sourceX;
|
|
506
|
+
const targetY = destinationYResult.value + row - sourceY;
|
|
507
|
+
if (targetX < 0 || targetY < 0 || targetX >= width.value || targetY >= height.value)
|
|
508
|
+
continue;
|
|
509
|
+
const sourceOffset = (row * source.width + column) * 4;
|
|
510
|
+
writePixel(
|
|
511
|
+
data,
|
|
512
|
+
width.value,
|
|
513
|
+
targetX,
|
|
514
|
+
targetY,
|
|
515
|
+
snapshot.subarray(sourceOffset, sourceOffset + 4)
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return ok(void 0);
|
|
520
|
+
},
|
|
521
|
+
fillNoise(seed, noiseOptions) {
|
|
522
|
+
if (!Number.isFinite(seed)) return invalid("noise", "seed", String(seed), "a finite number");
|
|
523
|
+
const min = noiseOptions?.min ?? 0;
|
|
524
|
+
const max = noiseOptions?.max ?? 255;
|
|
525
|
+
const alpha = noiseOptions?.alpha ?? 255;
|
|
526
|
+
for (const [field, value] of [
|
|
527
|
+
["min", min],
|
|
528
|
+
["max", max],
|
|
529
|
+
["alpha", alpha]
|
|
530
|
+
]) {
|
|
531
|
+
if (!Number.isFinite(value) || value < 0 || value > 255) {
|
|
532
|
+
return invalid("noise", field, value, "a finite number in [0, 255]");
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (min > max) return invalid("noise", "min", min, "a value no greater than max");
|
|
536
|
+
let state = Math.trunc(seed) >>> 0 || 1831565813;
|
|
537
|
+
const span = max - min;
|
|
538
|
+
for (let index = 0; index < data.length; index += 4) {
|
|
539
|
+
state = nextRandom(state);
|
|
540
|
+
const value = min + state / 4294967296 * span;
|
|
541
|
+
const channel = Math.round(value);
|
|
542
|
+
data[index] = channel;
|
|
543
|
+
data[index + 1] = channel;
|
|
544
|
+
data[index + 2] = channel;
|
|
545
|
+
data[index + 3] = Math.round(alpha);
|
|
546
|
+
}
|
|
547
|
+
return ok(void 0);
|
|
548
|
+
},
|
|
549
|
+
noise(seed, noiseOptions) {
|
|
550
|
+
return surface.fillNoise(seed, noiseOptions);
|
|
551
|
+
},
|
|
552
|
+
toDecodedImage() {
|
|
553
|
+
return {
|
|
554
|
+
bytes: data.slice(),
|
|
555
|
+
width: width.value,
|
|
556
|
+
height: height.value,
|
|
557
|
+
mime: "image/png",
|
|
558
|
+
colorSpace,
|
|
559
|
+
mipmap
|
|
560
|
+
};
|
|
561
|
+
},
|
|
562
|
+
toTextureAsset() {
|
|
563
|
+
return {
|
|
564
|
+
kind: "texture",
|
|
565
|
+
shape: {
|
|
566
|
+
viewDimension: "2d",
|
|
567
|
+
extent: { width: width.value, height: height.value }
|
|
568
|
+
},
|
|
569
|
+
format: colorSpace === "srgb" ? "rgba8unorm-srgb" : "rgba8unorm",
|
|
570
|
+
data: data.slice(),
|
|
571
|
+
colorSpace,
|
|
572
|
+
mips: mipmap ? { kind: "generate" } : { kind: "none" }
|
|
573
|
+
};
|
|
574
|
+
},
|
|
575
|
+
toAssetPack(meta) {
|
|
576
|
+
return toAssetPack(surface.toDecodedImage(), meta);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
return ok(surface);
|
|
580
|
+
}
|
|
581
|
+
function createPixelSurface(options) {
|
|
582
|
+
return makeSurface(options);
|
|
583
|
+
}
|
|
584
|
+
|
|
276
585
|
// src/source-key.ts
|
|
277
586
|
function deriveImageSourceKey(role, _locator) {
|
|
278
587
|
const normalizedRole = role.trim();
|
|
@@ -338,7 +647,7 @@ function reimportReuseMeta(decoded, existing) {
|
|
|
338
647
|
}
|
|
339
648
|
return out;
|
|
340
649
|
}
|
|
341
|
-
function
|
|
650
|
+
function invalid2(guid, expected, reason) {
|
|
342
651
|
return err({
|
|
343
652
|
code: "asset-package-invalid",
|
|
344
653
|
expected,
|
|
@@ -377,7 +686,7 @@ async function readImageSurface(input, kind, expected) {
|
|
|
377
686
|
const { envelope, artifacts } = input;
|
|
378
687
|
const payload = envelope.payload;
|
|
379
688
|
if (payload === null || typeof payload !== "object" || payload.kind !== kind) {
|
|
380
|
-
return
|
|
689
|
+
return invalid2(envelope.guid, expected, `${kind} owner validation failed`);
|
|
381
690
|
}
|
|
382
691
|
const body = envelope.artifacts.body ?? envelope.artifacts.atlas;
|
|
383
692
|
let data = imageBytes(payload.data);
|
|
@@ -389,17 +698,17 @@ async function readImageSurface(input, kind, expected) {
|
|
|
389
698
|
if (body.assetCodec?.name === "basis" && body.assetCodec.container !== void 0) {
|
|
390
699
|
const candidate = payload;
|
|
391
700
|
if (candidate.colorSpace !== "srgb" && candidate.colorSpace !== "linear") {
|
|
392
|
-
return
|
|
701
|
+
return invalid2(envelope.guid, expected, `${kind} color space is invalid`);
|
|
393
702
|
}
|
|
394
703
|
const target = compressedImageTarget(candidate.colorSpace);
|
|
395
704
|
const transcoded = body.assetCodec.container === "ktx2" ? await parseKtx2(bytes).then(
|
|
396
705
|
(parsed) => parsed.ok ? transcodeKtx2(parsed.value, target) : parsed
|
|
397
706
|
) : await transcodeBasis(bytes, target);
|
|
398
707
|
if (!transcoded.ok) {
|
|
399
|
-
return
|
|
708
|
+
return invalid2(envelope.guid, expected, `codec:${transcoded.error.code}`);
|
|
400
709
|
}
|
|
401
710
|
const mip = transcoded.value.mips[0];
|
|
402
|
-
if (mip === void 0) return
|
|
711
|
+
if (mip === void 0) return invalid2(envelope.guid, expected, "codec:base-mip-missing");
|
|
403
712
|
data = mip.data;
|
|
404
713
|
return readDecodedSurface(
|
|
405
714
|
envelope.guid,
|
|
@@ -422,7 +731,7 @@ async function readImageSurface(input, kind, expected) {
|
|
|
422
731
|
}
|
|
423
732
|
function readDecodedSurface(guid, expected, kind, candidate) {
|
|
424
733
|
if (kind === "texture" ? !validTextureSurface(candidate) : !validEquirectSurface(candidate)) {
|
|
425
|
-
return
|
|
734
|
+
return invalid2(guid, expected, "image owner validation failed");
|
|
426
735
|
}
|
|
427
736
|
return ok(candidate);
|
|
428
737
|
}
|
|
@@ -453,30 +762,6 @@ var equirectContribution = {
|
|
|
453
762
|
}
|
|
454
763
|
};
|
|
455
764
|
|
|
456
|
-
|
|
457
|
-
function toAssetPack(decoded, meta) {
|
|
458
|
-
return {
|
|
459
|
-
schemaVersion: "1.0.0",
|
|
460
|
-
kind: "external-asset-package",
|
|
461
|
-
importer: "image",
|
|
462
|
-
source: "",
|
|
463
|
-
importSettings: {
|
|
464
|
-
colorSpace: meta.colorSpace,
|
|
465
|
-
mipmap: meta.mipmap,
|
|
466
|
-
addressMode: meta.addressMode,
|
|
467
|
-
filterMode: meta.filterMode,
|
|
468
|
-
...meta.downscaleMaxDimension !== void 0 ? { downscaleMaxDimension: meta.downscaleMaxDimension } : {}
|
|
469
|
-
},
|
|
470
|
-
subAssets: [
|
|
471
|
-
{
|
|
472
|
-
guid: meta.guid,
|
|
473
|
-
sourceIndex: 0,
|
|
474
|
-
kind: "texture"
|
|
475
|
-
}
|
|
476
|
-
]
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
export { IMAGE_ERROR_EXPECTED, ImageErrorImpl, decodeHdr, decodeImageInBrowser, deriveImageSourceKey, equirectContribution, imageError, loadJpeg, loadUpng, reimportReuseMeta, subAssetKey, subAssetKeyEqual, textureContribution, toAssetPack };
|
|
765
|
+
export { IMAGE_ERROR_EXPECTED, ImageErrorImpl, createPixelSurface, decodeHdr, decodeImageInBrowser, deriveImageSourceKey, equirectContribution, imageError, loadJpeg, loadUpng, reimportReuseMeta, subAssetKey, subAssetKeyEqual, textureContribution, toAssetPack };
|
|
481
766
|
//# sourceMappingURL=index.mjs.map
|
|
482
767
|
//# sourceMappingURL=index.mjs.map
|