@forgeax/engine-image 0.1.4 → 0.1.6

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 (49) hide show
  1. package/README.md +5 -7
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/decode-image-from-file.d.ts.map +1 -1
  4. package/dist/decode-image-from-file.mjs +5 -135
  5. package/dist/decode-image-from-file.mjs.map +1 -1
  6. package/dist/hdr-decoder.mjs +1 -1
  7. package/dist/hdr-decoder.mjs.map +1 -1
  8. package/dist/image-importer.d.ts.map +1 -1
  9. package/dist/image-importer.mjs +20 -100
  10. package/dist/image-importer.mjs.map +1 -1
  11. package/dist/index.d.ts +1 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.mjs +2 -36
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/ktx2-encode.d.ts +2 -5
  16. package/dist/ktx2-encode.d.ts.map +1 -1
  17. package/dist/ktx2-encode.mjs +15 -17
  18. package/dist/ktx2-encode.mjs.map +1 -1
  19. package/dist/parse-image.d.ts +0 -1
  20. package/dist/parse-image.d.ts.map +1 -1
  21. package/dist/parse-image.mjs +3 -80
  22. package/dist/parse-image.mjs.map +1 -1
  23. package/package.json +6 -6
  24. package/src/__tests__/image.unit.test.ts +28 -162
  25. package/src/decode-image-from-file.ts +3 -68
  26. package/src/errors.ts +1 -1
  27. package/src/image-decoder-browser.ts +1 -1
  28. package/src/image-importer.ts +3 -4
  29. package/src/index.ts +3 -5
  30. package/src/ktx2-encode.ts +17 -21
  31. package/src/parse-image.ts +3 -103
  32. package/dist/__tests__/ktx2-encode-mode-owner.test-d.d.ts +0 -2
  33. package/dist/__tests__/ktx2-encode-mode-owner.test-d.d.ts.map +0 -1
  34. package/dist/__tests__/runtime-decode.unit.test.d.ts +0 -2
  35. package/dist/__tests__/runtime-decode.unit.test.d.ts.map +0 -1
  36. package/dist/__tests__/tga.unit.test.d.ts +0 -2
  37. package/dist/__tests__/tga.unit.test.d.ts.map +0 -1
  38. package/dist/runtime/__tests__/asset-decoders.unit.test.d.ts +0 -2
  39. package/dist/runtime/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
  40. package/dist/runtime/decode-image-bytes.d.ts +0 -7
  41. package/dist/runtime/decode-image-bytes.d.ts.map +0 -1
  42. package/dist/runtime/image-error.d.ts +0 -3
  43. package/dist/runtime/image-error.d.ts.map +0 -1
  44. package/src/__tests__/ktx2-encode-mode-owner.test-d.ts +0 -70
  45. package/src/__tests__/runtime-decode.unit.test.ts +0 -22
  46. package/src/__tests__/tga.unit.test.ts +0 -59
  47. package/src/runtime/__tests__/asset-decoders.unit.test.ts +0 -66
  48. package/src/runtime/decode-image-bytes.ts +0 -41
  49. package/src/runtime/image-error.ts +0 -8
@@ -21,7 +21,7 @@ var init_errors = __esm({
21
21
  "src/errors.ts"() {
22
22
  IMAGE_ERROR_EXPECTED = {
23
23
  "image-decode-failed": "PNG / JPG byte stream decodes successfully",
24
- "image-format-unsupported": "mime is one of ['image/png', 'image/jpeg', 'image/x-tga']; uploadTexture format <-> colorSpace family agrees",
24
+ "image-format-unsupported": "mime is one of ['image/png', 'image/jpeg']; uploadTexture format <-> colorSpace family agrees",
25
25
  "image-dimension-out-of-bounds": "width and height fall under device caps maxTextureDimension2D (or 16384 hard cap)",
26
26
  "image-meta-missing": "<source>.meta.json sidecar (importer: 'image') exists in the same directory",
27
27
  "image-hdr-decode-failed": "Radiance RGBE header is valid and pixel data decodes successfully",
@@ -238,36 +238,34 @@ var init_hdr_decoder = __esm({
238
238
  LF = 10;
239
239
  }
240
240
  });
241
- var COMPRESSION_MODES = ["auto", "etc1s", "uastc", "none"];
242
- var RESOLVED_ENCODE_MODES = ["etc1s", "uastc", "uastc-hdr", "none"];
243
241
  function resolveEncodeMode(mode, source) {
244
242
  switch (mode) {
245
- case COMPRESSION_MODES[3]:
246
- return RESOLVED_ENCODE_MODES[3];
247
- case COMPRESSION_MODES[1]:
248
- return RESOLVED_ENCODE_MODES[0];
249
- case COMPRESSION_MODES[2]:
250
- return source.isHdr ? RESOLVED_ENCODE_MODES[2] : RESOLVED_ENCODE_MODES[1];
251
- case COMPRESSION_MODES[0]:
252
- if (source.isHdr) return RESOLVED_ENCODE_MODES[2];
253
- return source.colorSpace === "srgb" ? RESOLVED_ENCODE_MODES[0] : RESOLVED_ENCODE_MODES[1];
243
+ case "none":
244
+ return "none";
245
+ case "etc1s":
246
+ return "etc1s";
247
+ case "uastc":
248
+ return source.isHdr ? "uastc-hdr" : "uastc";
249
+ case "auto":
250
+ if (source.isHdr) return "uastc-hdr";
251
+ return source.colorSpace === "srgb" ? "etc1s" : "uastc";
254
252
  }
255
253
  }
256
254
  function basisEncodeParamsFor(mode, source) {
257
255
  const resolved = resolveEncodeMode(mode, source);
258
256
  const srgbColor = source.colorSpace === "srgb";
259
257
  switch (resolved) {
260
- case RESOLVED_ENCODE_MODES[3]:
258
+ case "none":
261
259
  return null;
262
- case RESOLVED_ENCODE_MODES[0]:
260
+ case "etc1s":
263
261
  return {
264
- mode: RESOLVED_ENCODE_MODES[0],
262
+ mode: "etc1s",
265
263
  srgb: srgbColor,
266
264
  perceptual: srgbColor,
267
265
  uastcSupercompression: false,
268
266
  mipGen: false
269
267
  };
270
- case RESOLVED_ENCODE_MODES[1]:
268
+ case "uastc":
271
269
  return {
272
270
  mode: "uastc-ldr",
273
271
  srgb: srgbColor,
@@ -275,9 +273,9 @@ function basisEncodeParamsFor(mode, source) {
275
273
  uastcSupercompression: true,
276
274
  mipGen: false
277
275
  };
278
- case RESOLVED_ENCODE_MODES[2]:
276
+ case "uastc-hdr":
279
277
  return {
280
- mode: RESOLVED_ENCODE_MODES[2],
278
+ mode: "uastc-hdr",
281
279
  srgb: false,
282
280
  perceptual: false,
283
281
  uastcSupercompression: false,
@@ -369,7 +367,7 @@ function downscaleRgba(bytes, width, height, maxDimension) {
369
367
  // src/parse-image.ts
370
368
  init_result();
371
369
  var DEFAULT_MAX_DIMENSION = 16384;
372
- var SUPPORTED_MIMES = ["image/png", "image/jpeg", "image/x-tga"];
370
+ var SUPPORTED_MIMES = ["image/png", "image/jpeg"];
373
371
  function parseImage(bytes, mime, opts = {}) {
374
372
  if (!SUPPORTED_MIMES.includes(mime)) {
375
373
  return err(
@@ -401,17 +399,12 @@ function parseImage(bytes, mime, opts = {}) {
401
399
  );
402
400
  }
403
401
  rgba = new Uint8Array(first);
404
- } else if (mime === "image/jpeg") {
402
+ } else {
405
403
  const jpegMod = jpeg.default ?? jpeg;
406
404
  const decoded = jpegMod.decode(bytes, { useTArray: true, formatAsRGBA: true });
407
405
  width = decoded.width;
408
406
  height = decoded.height;
409
407
  rgba = decoded.data;
410
- } else {
411
- const decoded = decodeTga(bytes);
412
- width = decoded.width;
413
- height = decoded.height;
414
- rgba = decoded.bytes;
415
408
  }
416
409
  } catch (e) {
417
410
  return err(
@@ -448,85 +441,12 @@ function parseImage(bytes, mime, opts = {}) {
448
441
  mipmap: opts.mipmap ?? true
449
442
  });
450
443
  }
451
- function decodeTga(bytes) {
452
- if (bytes.length < 18) throw new Error("TGA header is truncated");
453
- const colorMapType = bytes[1];
454
- const imageType = bytes[2];
455
- const idLength = bytes[0] ?? 0;
456
- const width = (bytes[12] ?? 0) | (bytes[13] ?? 0) << 8;
457
- const height = (bytes[14] ?? 0) | (bytes[15] ?? 0) << 8;
458
- const pixelDepth = bytes[16] ?? 0;
459
- const descriptor = bytes[17] ?? 0;
460
- if (colorMapType !== 0) throw new Error("color-mapped TGA is unsupported");
461
- if (width < 1 || height < 1) throw new Error("TGA dimensions must be positive");
462
- const isTrueColor = imageType === 2 || imageType === 10;
463
- const isGray = imageType === 3 || imageType === 11;
464
- if (!isTrueColor && !isGray) throw new Error(`TGA image type ${imageType} is unsupported`);
465
- if (isTrueColor && pixelDepth !== 24 && pixelDepth !== 32) {
466
- throw new Error(`TGA true-color depth ${pixelDepth} is unsupported`);
467
- }
468
- if (isGray && pixelDepth !== 8)
469
- throw new Error(`TGA grayscale depth ${pixelDepth} is unsupported`);
470
- const bytesPerPixel = pixelDepth / 8;
471
- let offset = 18 + idLength;
472
- const pixelCount = width * height;
473
- const out = new Uint8Array(pixelCount * 4);
474
- const topOrigin = (descriptor & 32) !== 0;
475
- const rightOrigin = (descriptor & 16) !== 0;
476
- let filePixel = 0;
477
- const writePixel = (pixel) => {
478
- if (filePixel >= pixelCount) throw new Error("TGA pixel data has too many pixels");
479
- const fileX = filePixel % width;
480
- const fileY = Math.floor(filePixel / width);
481
- const x = rightOrigin ? width - 1 - fileX : fileX;
482
- const y = topOrigin ? fileY : height - 1 - fileY;
483
- const destination = (y * width + x) * 4;
484
- if (isGray) {
485
- const value = pixel[0] ?? 0;
486
- out[destination] = value;
487
- out[destination + 1] = value;
488
- out[destination + 2] = value;
489
- out[destination + 3] = 255;
490
- } else {
491
- out[destination] = pixel[2] ?? 0;
492
- out[destination + 1] = pixel[1] ?? 0;
493
- out[destination + 2] = pixel[0] ?? 0;
494
- out[destination + 3] = bytesPerPixel === 4 ? pixel[3] ?? 255 : 255;
495
- }
496
- filePixel += 1;
497
- };
498
- const readPixel = () => {
499
- if (offset + bytesPerPixel > bytes.length) throw new Error("TGA pixel data is truncated");
500
- const pixel = bytes.slice(offset, offset + bytesPerPixel);
501
- offset += bytesPerPixel;
502
- return pixel;
503
- };
504
- if (imageType === 2 || imageType === 3) {
505
- while (filePixel < pixelCount) writePixel(readPixel());
506
- } else {
507
- while (filePixel < pixelCount) {
508
- if (offset >= bytes.length) throw new Error("TGA RLE packet header is truncated");
509
- const packet = bytes[offset++] ?? 0;
510
- const count = (packet & 127) + 1;
511
- if (filePixel + count > pixelCount) throw new Error("TGA RLE packet exceeds image bounds");
512
- if ((packet & 128) !== 0) {
513
- const pixel = readPixel();
514
- for (let i = 0; i < count; i++) writePixel(pixel);
515
- } else {
516
- for (let i = 0; i < count; i++) writePixel(readPixel());
517
- }
518
- }
519
- }
520
- if (filePixel !== pixelCount) throw new Error("TGA pixel count mismatch");
521
- return { width, height, bytes: out };
522
- }
523
444
 
524
445
  // src/image-importer.ts
525
446
  function mimeFromSource(source) {
526
447
  const lower = source.toLowerCase();
527
448
  if (lower.endsWith(".png")) return "image/png";
528
449
  if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
529
- if (lower.endsWith(".tga")) return "image/x-tga";
530
450
  return void 0;
531
451
  }
532
452
  function requiredImageOutputKind(source) {
@@ -1027,7 +947,7 @@ async function importImage(ctx) {
1027
947
  }
1028
948
  if (mime === void 0) {
1029
949
  throw new Error(
1030
- `imageImporter: unsupported source extension for "${ctx.source}" (expected .png / .jpg / .jpeg / .tga / .hdr / .ktx2 / .basis)`
950
+ `imageImporter: unsupported source extension for "${ctx.source}" (expected .png / .jpg / .jpeg / .hdr / .ktx2 / .basis)`
1031
951
  );
1032
952
  }
1033
953
  const colorSpace = ctx.importSettings.colorSpace === "srgb" ? "srgb" : "linear";
@@ -1047,7 +967,7 @@ async function importImage(ctx) {
1047
967
  "decode",
1048
968
  "ldr",
1049
969
  ctx.source,
1050
- "valid PNG, JPEG, or TGA bytes to decode into RGBA pixels",
970
+ "valid PNG or JPEG bytes to decode into RGBA pixels",
1051
971
  `image:${decoded.error.code}`,
1052
972
  "repair the source image bytes and retry the import"
1053
973
  )