@forgeax/engine-image 0.1.19 → 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.
Files changed (42) hide show
  1. package/README.md +61 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/pixel-surface.unit.test.d.ts +2 -0
  4. package/dist/__tests__/pixel-surface.unit.test.d.ts.map +1 -0
  5. package/dist/__tests__/texture-source-descriptor.integration.test.d.ts +2 -0
  6. package/dist/__tests__/texture-source-descriptor.integration.test.d.ts.map +1 -0
  7. package/dist/decode-image-from-file.mjs +2 -1
  8. package/dist/decode-image-from-file.mjs.map +1 -1
  9. package/dist/errors.d.ts.map +1 -1
  10. package/dist/hdr-decoder.mjs +2 -1
  11. package/dist/hdr-decoder.mjs.map +1 -1
  12. package/dist/image-importer.d.ts.map +1 -1
  13. package/dist/image-importer.mjs +222 -16
  14. package/dist/image-importer.mjs.map +1 -1
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.mjs +341 -43
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/parse-image.mjs +2 -1
  20. package/dist/parse-image.mjs.map +1 -1
  21. package/dist/pixel-surface.d.ts +53 -0
  22. package/dist/pixel-surface.d.ts.map +1 -0
  23. package/dist/runtime/asset-decoders.d.ts.map +1 -1
  24. package/dist/texture/importer.d.ts +42 -0
  25. package/dist/texture/importer.d.ts.map +1 -0
  26. package/dist/texture/source-descriptor.d.ts +24 -0
  27. package/dist/texture/source-descriptor.d.ts.map +1 -0
  28. package/package.json +6 -6
  29. package/src/__tests__/errors.test-d.ts +11 -3
  30. package/src/__tests__/image-importer-conversion-failure.unit.test.ts +31 -2
  31. package/src/__tests__/image-importer-topology.unit.test.ts +2 -2
  32. package/src/__tests__/image.unit.test.ts +2 -4
  33. package/src/__tests__/ktx2-basis-importer.unit.test.ts +2 -3
  34. package/src/__tests__/pixel-surface.unit.test.ts +94 -0
  35. package/src/__tests__/texture-source-descriptor.integration.test.ts +117 -0
  36. package/src/errors.ts +2 -0
  37. package/src/image-importer.ts +24 -14
  38. package/src/index.ts +8 -0
  39. package/src/pixel-surface.ts +428 -0
  40. package/src/runtime/asset-decoders.ts +40 -11
  41. package/src/texture/importer.ts +198 -0
  42. package/src/texture/source-descriptor.ts +123 -0
@@ -0,0 +1,123 @@
1
+ import type { TextureMipPolicy, TextureShape } from '@forgeax/engine-types';
2
+ import {
3
+ err,
4
+ ok,
5
+ type Result,
6
+ type TextureError,
7
+ validateTextureShape,
8
+ } from '@forgeax/engine-types';
9
+
10
+ /** Versioned source-side declaration for one logical sampled texture. */
11
+ export interface TextureSourceDescriptor {
12
+ readonly schemaVersion: '1';
13
+ readonly shape: TextureShape;
14
+ readonly format: GPUTextureFormat;
15
+ readonly colorSpace: 'srgb' | 'linear';
16
+ readonly mips: TextureMipPolicy;
17
+ readonly rawSibling: string;
18
+ }
19
+
20
+ export interface TextureSourceDescriptorError {
21
+ readonly code: 'texture-source-descriptor-invalid';
22
+ readonly expected: string;
23
+ readonly hint: string;
24
+ readonly detail: { readonly field: string; readonly actual: unknown };
25
+ }
26
+
27
+ export type TextureSourceDescriptorResult = Result<
28
+ TextureSourceDescriptor,
29
+ TextureSourceDescriptorError | TextureError
30
+ >;
31
+
32
+ function record(value: unknown): value is Record<string, unknown> {
33
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
34
+ }
35
+
36
+ function positiveInteger(value: unknown): value is number {
37
+ return typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
38
+ }
39
+
40
+ function parseShape(value: unknown): TextureShape | undefined {
41
+ if (!record(value) || !record(value.extent)) return undefined;
42
+ const extent = value.extent;
43
+ if (
44
+ value.viewDimension === '2d' &&
45
+ positiveInteger(extent.width) &&
46
+ positiveInteger(extent.height)
47
+ ) {
48
+ if (extent.layers === undefined && extent.depth === undefined) {
49
+ return { viewDimension: '2d', extent: { width: extent.width, height: extent.height } };
50
+ }
51
+ }
52
+ if (
53
+ value.viewDimension === '2d-array' &&
54
+ positiveInteger(extent.width) &&
55
+ positiveInteger(extent.height) &&
56
+ positiveInteger(extent.layers) &&
57
+ extent.depth === undefined
58
+ ) {
59
+ return {
60
+ viewDimension: '2d-array',
61
+ extent: { width: extent.width, height: extent.height, layers: extent.layers },
62
+ };
63
+ }
64
+ if (
65
+ value.viewDimension === '3d' &&
66
+ positiveInteger(extent.width) &&
67
+ positiveInteger(extent.height) &&
68
+ positiveInteger(extent.depth) &&
69
+ extent.layers === undefined
70
+ ) {
71
+ return {
72
+ viewDimension: '3d',
73
+ extent: { width: extent.width, height: extent.height, depth: extent.depth },
74
+ };
75
+ }
76
+ return undefined;
77
+ }
78
+
79
+ function parseMips(value: unknown): TextureMipPolicy | undefined {
80
+ if (!record(value)) return undefined;
81
+ if (value.kind === 'none' || value.kind === 'generate') return { kind: value.kind };
82
+ if (value.kind === 'packed' && positiveInteger(value.levelCount)) {
83
+ return { kind: 'packed', levelCount: value.levelCount };
84
+ }
85
+ return undefined;
86
+ }
87
+
88
+ function descriptorError(field: string, actual: unknown): TextureSourceDescriptorError {
89
+ return {
90
+ code: 'texture-source-descriptor-invalid',
91
+ expected: 'version 1 descriptor with shape, format, colorSpace, mips, and rawSibling',
92
+ hint: 'repair the texture descriptor and re-import the same texture GUID',
93
+ detail: { field, actual },
94
+ };
95
+ }
96
+
97
+ /** Parse and validate source facts before any raw sibling bytes are consumed. */
98
+ export function parseTextureSourceDescriptor(value: unknown): TextureSourceDescriptorResult {
99
+ if (!record(value)) return err(descriptorError('descriptor', value));
100
+ if (value.schemaVersion !== '1')
101
+ return err(descriptorError('schemaVersion', value.schemaVersion));
102
+ const shape = parseShape(value.shape);
103
+ if (shape === undefined) return err(descriptorError('shape', value.shape));
104
+ const mips = parseMips(value.mips);
105
+ if (mips === undefined) return err(descriptorError('mips', value.mips));
106
+ if (typeof value.format !== 'string') return err(descriptorError('format', value.format));
107
+ if (value.colorSpace !== 'srgb' && value.colorSpace !== 'linear') {
108
+ return err(descriptorError('colorSpace', value.colorSpace));
109
+ }
110
+ if (typeof value.rawSibling !== 'string' || value.rawSibling.trim().length === 0) {
111
+ return err(descriptorError('rawSibling', value.rawSibling));
112
+ }
113
+ const shapeResult = validateTextureShape(shape, mips, value.format as GPUTextureFormat);
114
+ if (!shapeResult.ok) return shapeResult;
115
+ return ok({
116
+ schemaVersion: '1',
117
+ shape,
118
+ format: value.format as GPUTextureFormat,
119
+ colorSpace: value.colorSpace,
120
+ mips,
121
+ rawSibling: value.rawSibling,
122
+ });
123
+ }