@flighthq/texture-formats 0.3.0-next.906.07cea63 → 0.3.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/dist/contract.d.ts +8 -7
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +8 -7
- package/dist/contract.js.map +1 -1
- package/dist/detectTextureContainer.d.ts +2 -1
- package/dist/detectTextureContainer.d.ts.map +1 -1
- package/dist/detectTextureContainer.js +0 -6
- package/dist/detectTextureContainer.js.map +1 -1
- package/dist/explainTextureContainerParse.d.ts +3 -0
- package/dist/explainTextureContainerParse.d.ts.map +1 -0
- package/dist/explainTextureContainerParse.js +27 -0
- package/dist/explainTextureContainerParse.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parseAtf.d.ts +2 -0
- package/dist/parseAtf.d.ts.map +1 -1
- package/dist/parseAtf.js +28 -13
- package/dist/parseAtf.js.map +1 -1
- package/dist/parseBasis.d.ts +2 -0
- package/dist/parseBasis.d.ts.map +1 -1
- package/dist/parseBasis.js +22 -8
- package/dist/parseBasis.js.map +1 -1
- package/dist/parseDds.d.ts +2 -0
- package/dist/parseDds.d.ts.map +1 -1
- package/dist/parseDds.js +26 -10
- package/dist/parseDds.js.map +1 -1
- package/dist/parseKtx2.d.ts +2 -0
- package/dist/parseKtx2.d.ts.map +1 -1
- package/dist/parseKtx2.js +19 -6
- package/dist/parseKtx2.js.map +1 -1
- package/package.json +4 -2
- package/src/explainTextureContainerParse.test.ts +65 -0
- package/src/parseAtf.test.ts +7 -1
- package/src/parseBasis.test.ts +7 -1
- package/src/parseDds.test.ts +7 -1
- package/src/parseKtx2.test.ts +7 -1
package/dist/contract.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
1
|
+
export { detectTextureContainer } from './detectTextureContainer';
|
|
2
|
+
export { explainTextureContainerParse } from './explainTextureContainerParse';
|
|
3
|
+
export { parseAtf } from './parseAtf';
|
|
4
|
+
export { parseBasis } from './parseBasis';
|
|
5
|
+
export { parseDds } from './parseDds';
|
|
6
|
+
export { parseKtx2 } from './parseKtx2';
|
|
7
|
+
export { selectTextureContainer } from './selectTextureContainer';
|
|
8
|
+
export { computeTextureContainerLevels, getTextureContainerLevelByteLength } from './textureLevelLayout';
|
|
8
9
|
//# sourceMappingURL=contract.d.ts.map
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/contract.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
1
|
+
export { detectTextureContainer } from './detectTextureContainer';
|
|
2
|
+
export { explainTextureContainerParse } from './explainTextureContainerParse';
|
|
3
|
+
export { parseAtf } from './parseAtf';
|
|
4
|
+
export { parseBasis } from './parseBasis';
|
|
5
|
+
export { parseDds } from './parseDds';
|
|
6
|
+
export { parseKtx2 } from './parseKtx2';
|
|
7
|
+
export { selectTextureContainer } from './selectTextureContainer';
|
|
8
|
+
export { computeTextureContainerLevels, getTextureContainerLevelByteLength } from './textureLevelLayout';
|
|
8
9
|
//# sourceMappingURL=contract.js.map
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import type { TextureContainerKind } from '@flighthq/types/contract';
|
|
2
|
+
export declare function detectTextureContainer(bytes: Readonly<Uint8Array>): TextureContainerKind | null;
|
|
2
3
|
//# sourceMappingURL=detectTextureContainer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detectTextureContainer.d.ts","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAMA,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"detectTextureContainer.d.ts","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAErE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,oBAAoB,GAAG,IAAI,CAW/F"}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
// Sniffs which GPU texture container a byte buffer holds from its magic bytes — `'ktx2'`, `'dds'`,
|
|
2
|
-
// `'basis'`, `'atf'`, or `null` when the header is too short or unrecognized. The texture-container
|
|
3
|
-
// sibling of `detectImageMimeType`: a cheap dispatcher to pick a `parse*` function without fully
|
|
4
|
-
// parsing, and the single point of container identification in the SDK. `'atf'` alone maps to the
|
|
5
|
-
// array-returning `parseAtf` (an ATF holds one-or-more peer encodings); the others map to a single
|
|
6
|
-
// `parse*` returning one `TextureContainer`.
|
|
7
1
|
export function detectTextureContainer(bytes) {
|
|
8
2
|
if (bytes.byteLength >= 12 && isKtx2Magic(bytes))
|
|
9
3
|
return 'ktx2';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detectTextureContainer.js","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detectTextureContainer.js","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,sBAAsB,CAAC,KAA2B;IAChE,IAAI,KAAK,CAAC,UAAU,IAAI,EAAE,IAAI,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAChE,oCAAoC;IACpC,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9G,OAAO,KAAK,CAAC;IACf,CAAC;IACD,8BAA8B;IAC9B,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACvG,mDAAmD;IACnD,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IACpF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qBAAqB;AACrB,MAAM,SAAS,GAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainTextureContainerParse.d.ts","sourceRoot":"","sources":["../src/explainTextureContainerParse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAUjF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gCAAgC,GAAG,IAAI,CAMjH"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { detectTextureContainer } from './detectTextureContainer';
|
|
2
|
+
import { getAtfParseFailureReason } from './parseAtf';
|
|
3
|
+
import { getBasisParseFailureReason } from './parseBasis';
|
|
4
|
+
import { getDdsParseFailureReason } from './parseDds';
|
|
5
|
+
import { getKtx2ParseFailureReason } from './parseKtx2';
|
|
6
|
+
// Explains why the detected texture container's parser would return null. Returns null when parsing
|
|
7
|
+
// succeeds. The query does not retain payload bytes or expose parser-internal reader state.
|
|
8
|
+
export function explainTextureContainerParse(bytes) {
|
|
9
|
+
const container = detectTextureContainer(bytes);
|
|
10
|
+
if (container === null)
|
|
11
|
+
return { container: null, reason: 'container-unrecognized' };
|
|
12
|
+
const reason = getParseFailureReason(container, bytes);
|
|
13
|
+
return reason === null ? null : { container, reason };
|
|
14
|
+
}
|
|
15
|
+
function getParseFailureReason(container, bytes) {
|
|
16
|
+
switch (container) {
|
|
17
|
+
case 'atf':
|
|
18
|
+
return getAtfParseFailureReason(bytes);
|
|
19
|
+
case 'basis':
|
|
20
|
+
return getBasisParseFailureReason(bytes);
|
|
21
|
+
case 'dds':
|
|
22
|
+
return getDdsParseFailureReason(bytes);
|
|
23
|
+
case 'ktx2':
|
|
24
|
+
return getKtx2ParseFailureReason(bytes);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=explainTextureContainerParse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainTextureContainerParse.js","sourceRoot":"","sources":["../src/explainTextureContainerParse.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,oGAAoG;AACpG,4FAA4F;AAC5F,MAAM,UAAU,4BAA4B,CAAC,KAA2B;IACtE,MAAM,SAAS,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IAErF,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACvD,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACxD,CAAC;AAED,SAAS,qBAAqB,CAC5B,SAAqE,EACrE,KAA2B;IAE3B,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACzC,KAAK,OAAO;YACV,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;QAC3C,KAAK,KAAK;YACR,OAAO,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACzC,KAAK,MAAM;YACT,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { computeTextureContainerLevels, detectTextureContainer, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
|
|
1
|
+
export { computeTextureContainerLevels, detectTextureContainer, explainTextureContainerParse, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,4BAA4B,EAC5B,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { computeTextureContainerLevels, detectTextureContainer, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
|
|
1
|
+
export { computeTextureContainerLevels, detectTextureContainer, explainTextureContainerParse, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,4BAA4B,EAC5B,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
package/dist/parseAtf.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { TextureContainer } from '@flighthq/types/contract';
|
|
2
|
+
import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
|
|
3
|
+
export declare function getAtfParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
|
|
2
4
|
export declare function parseAtf(bytes: Readonly<Uint8Array>): TextureContainer[] | null;
|
|
3
5
|
//# sourceMappingURL=parseAtf.d.ts.map
|
package/dist/parseAtf.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseAtf.d.ts","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"parseAtf.d.ts","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AASnF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAI/G;AA6BD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAE/E"}
|
package/dist/parseAtf.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { createByteReader, hasByteReaderBytes, readByteReaderU24BigEndian, readByteReaderU32BigEndian, } from './byteReader';
|
|
2
|
+
export function getAtfParseFailureReason(bytes) {
|
|
3
|
+
const failure = { reason: null };
|
|
4
|
+
const containers = parseAtfInternal(bytes, failure);
|
|
5
|
+
return containers === null ? failure.reason : null;
|
|
6
|
+
}
|
|
2
7
|
// Parses an ATF (Adobe Texture Format) container into an ARRAY of peer `TextureContainer`s, or returns
|
|
3
8
|
// `null` if the bytes are not ATF, are truncated, or carry an unsupported ATF format code. ATF is the
|
|
4
9
|
// Flash/Stage3D/AIR GPU-texture container (an OpenFL/Lime feature target). Unlike KTX2/DDS/Basis, a
|
|
@@ -27,12 +32,15 @@ import { createByteReader, hasByteReaderBytes, readByteReaderU24BigEndian, readB
|
|
|
27
32
|
// 4/5/13 with alpha); the raw-BGRA codes (0/1) and the JPEG-XR/LZMA-wrapped variants are unsupported and
|
|
28
33
|
// return `null`.
|
|
29
34
|
export function parseAtf(bytes) {
|
|
35
|
+
return parseAtfInternal(bytes);
|
|
36
|
+
}
|
|
37
|
+
function parseAtfInternal(bytes, failure) {
|
|
30
38
|
if (!hasAtfSignature(bytes))
|
|
31
|
-
return
|
|
39
|
+
return reject(failure, 'container-unrecognized');
|
|
32
40
|
const versioned = bytes[6] === atfNewVersionMarker;
|
|
33
41
|
const headerOffset = versioned ? atfNewHeaderOffset : atfLegacyHeaderOffset;
|
|
34
42
|
if (bytes.byteLength < headerOffset + 4)
|
|
35
|
-
return
|
|
43
|
+
return reject(failure, 'header-truncated');
|
|
36
44
|
// `version` selects the block-length width (u24 for the legacy version-0 layout, u32 otherwise) and
|
|
37
45
|
// whether an ETC2 slot follows the DXT/ETC1/PVRTC trio.
|
|
38
46
|
const version = versioned ? bytes[7] : 0;
|
|
@@ -41,19 +49,21 @@ export function parseAtf(bytes) {
|
|
|
41
49
|
const lengthReader = createByteReader(bytes, versioned ? 8 : 3);
|
|
42
50
|
const payloadLength = versioned ? readByteReaderU32BigEndian(lengthReader) : readByteReaderU24BigEndian(lengthReader);
|
|
43
51
|
if (headerOffset + payloadLength > bytes.byteLength)
|
|
44
|
-
return
|
|
52
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
45
53
|
const typeFormatByte = bytes[headerOffset];
|
|
46
54
|
const log2Width = bytes[headerOffset + 1];
|
|
47
55
|
const log2Height = bytes[headerOffset + 2];
|
|
48
56
|
const mipCount = bytes[headerOffset + 3];
|
|
49
57
|
const formatCode = typeFormatByte & atfFormatCodeMask;
|
|
50
58
|
const alpha = atfAlphaFormatCodes.has(formatCode);
|
|
51
|
-
if (!alpha && !atfOpaqueFormatCodes.has(formatCode))
|
|
52
|
-
return
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
if (!alpha && !atfOpaqueFormatCodes.has(formatCode)) {
|
|
60
|
+
return reject(failure, 'format-unsupported'); // raw-BGRA / JPEG-XR / LZMA — unsupported
|
|
61
|
+
}
|
|
62
|
+
if (log2Width > atfMaxLog2Dimension || log2Height > atfMaxLog2Dimension) {
|
|
63
|
+
return reject(failure, 'structure-invalid');
|
|
64
|
+
}
|
|
55
65
|
if (mipCount < 1)
|
|
56
|
-
return
|
|
66
|
+
return reject(failure, 'structure-invalid');
|
|
57
67
|
const cube = (typeFormatByte & atfCubeFlag) !== 0;
|
|
58
68
|
const faces = cube ? 6 : 1;
|
|
59
69
|
const width = 1 << log2Width;
|
|
@@ -72,10 +82,10 @@ export function parseAtf(bytes) {
|
|
|
72
82
|
for (let level = 0; level < mipCount; level += 1) {
|
|
73
83
|
for (let slot = 0; slot < slotCount; slot += 1) {
|
|
74
84
|
if (!hasByteReaderBytes(reader, lengthWidth))
|
|
75
|
-
return
|
|
85
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
76
86
|
const blockLength = version === 0 ? readByteReaderU24BigEndian(reader) : readByteReaderU32BigEndian(reader);
|
|
77
87
|
if (!hasByteReaderBytes(reader, blockLength))
|
|
78
|
-
return
|
|
88
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
79
89
|
if (blockLength === 0)
|
|
80
90
|
continue; // absent encoding for this (side, level)
|
|
81
91
|
const byteOffset = reader.offset;
|
|
@@ -111,12 +121,17 @@ export function parseAtf(bytes) {
|
|
|
111
121
|
});
|
|
112
122
|
}
|
|
113
123
|
if (containers.length === 0)
|
|
114
|
-
return
|
|
124
|
+
return reject(failure, 'structure-invalid');
|
|
115
125
|
return containers;
|
|
116
126
|
}
|
|
127
|
+
function reject(failure, reason) {
|
|
128
|
+
if (failure !== undefined)
|
|
129
|
+
failure.reason = reason;
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
117
132
|
function hasAtfSignature(bytes) {
|
|
118
|
-
// 'ATF' — 0x41 0x54 0x46.
|
|
119
|
-
return bytes.byteLength >=
|
|
133
|
+
// 'ATF' — 0x41 0x54 0x46. Header length is validated separately after container detection.
|
|
134
|
+
return bytes.byteLength >= 3 && bytes[0] === 0x41 && bytes[1] === 0x54 && bytes[2] === 0x46;
|
|
120
135
|
}
|
|
121
136
|
const atfCubeFlag = 0x80;
|
|
122
137
|
const atfFormatCodeMask = 0x7f;
|
package/dist/parseAtf.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseAtf.js","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parseAtf.js","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"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"}
|
package/dist/parseBasis.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { TextureContainer } from '@flighthq/types/contract';
|
|
2
|
+
import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
|
|
3
|
+
export declare function getBasisParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
|
|
2
4
|
export declare function parseBasis(bytes: Readonly<Uint8Array>): TextureContainer | null;
|
|
3
5
|
//# sourceMappingURL=parseBasis.d.ts.map
|
package/dist/parseBasis.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseBasis.d.ts","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"parseBasis.d.ts","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAWnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAIjH;AAeD,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAE/E"}
|
package/dist/parseBasis.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { createByteReader, hasByteReaderBytes, readByteReaderU16, readByteReaderU24, readByteReaderU32, readByteReaderU8, } from './byteReader';
|
|
2
|
+
export function getBasisParseFailureReason(bytes) {
|
|
3
|
+
const failure = { reason: null };
|
|
4
|
+
const container = parseBasisInternal(bytes, failure);
|
|
5
|
+
return container === null ? failure.reason : null;
|
|
6
|
+
}
|
|
2
7
|
// Parses a Basis Universal `.basis` container into a `TextureContainer`, or returns `null` if the bytes
|
|
3
8
|
// are not a `.basis` file, are truncated, or carry an unknown texture format.
|
|
4
9
|
//
|
|
@@ -13,26 +18,30 @@ import { createByteReader, hasByteReaderBytes, readByteReaderU16, readByteReader
|
|
|
13
18
|
// faces per layer, and volume images become depth slices. Video frames are rejected because the common
|
|
14
19
|
// container descriptor cannot preserve their temporal/conditional-replenishment semantics truthfully.
|
|
15
20
|
export function parseBasis(bytes) {
|
|
21
|
+
return parseBasisInternal(bytes);
|
|
22
|
+
}
|
|
23
|
+
function parseBasisInternal(bytes, failure) {
|
|
16
24
|
if (!hasBasisSignature(bytes))
|
|
17
|
-
return
|
|
25
|
+
return reject(failure, 'container-unrecognized');
|
|
18
26
|
if (bytes.byteLength < basisHeaderMinSize)
|
|
19
|
-
return
|
|
27
|
+
return reject(failure, 'header-truncated');
|
|
20
28
|
const header = createByteReader(bytes, basisTotalSlicesOffset);
|
|
21
29
|
const totalSlices = readByteReaderU24(header); // m_total_slices (offset 14)
|
|
22
30
|
const totalImages = readByteReaderU24(header); // m_total_images (offset 17)
|
|
23
31
|
const format = basisTexFormat[bytes[basisTexFormatOffset]]; // m_tex_format (offset 20)
|
|
24
32
|
if (format === undefined)
|
|
25
|
-
return
|
|
33
|
+
return reject(failure, 'format-unsupported');
|
|
26
34
|
if (totalSlices === 0)
|
|
27
|
-
return
|
|
35
|
+
return reject(failure, 'structure-invalid');
|
|
28
36
|
const shape = getBasisTextureShape(bytes[basisTexTypeOffset], totalImages);
|
|
29
37
|
if (shape === null)
|
|
30
|
-
return
|
|
38
|
+
return reject(failure, 'format-unsupported');
|
|
31
39
|
const sliceDescReader = createByteReader(bytes, basisSliceDescOffsetField);
|
|
32
40
|
const sliceDescOffset = readByteReaderU32(sliceDescReader);
|
|
33
41
|
const table = createByteReader(bytes, sliceDescOffset);
|
|
34
|
-
if (!hasByteReaderBytes(table, totalSlices * basisSliceDescSize))
|
|
35
|
-
return
|
|
42
|
+
if (!hasByteReaderBytes(table, totalSlices * basisSliceDescSize)) {
|
|
43
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
44
|
+
}
|
|
36
45
|
const levels = [];
|
|
37
46
|
let baseWidth = 0;
|
|
38
47
|
let baseHeight = 0;
|
|
@@ -49,7 +58,7 @@ export function parseBasis(bytes) {
|
|
|
49
58
|
const byteLength = readByteReaderU32(table);
|
|
50
59
|
readByteReaderU16(table); // m_slice_data_crc16
|
|
51
60
|
if (byteOffset + byteLength > bytes.byteLength)
|
|
52
|
-
return
|
|
61
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
53
62
|
if (imageIndex === 0 && levelIndex === 0) {
|
|
54
63
|
baseWidth = width;
|
|
55
64
|
baseHeight = height;
|
|
@@ -70,6 +79,11 @@ export function parseBasis(bytes) {
|
|
|
70
79
|
width: baseWidth || (levels[0]?.width ?? 0),
|
|
71
80
|
};
|
|
72
81
|
}
|
|
82
|
+
function reject(failure, reason) {
|
|
83
|
+
if (failure !== undefined)
|
|
84
|
+
failure.reason = reason;
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
73
87
|
function getBasisTextureShape(textureType, totalImages) {
|
|
74
88
|
const images = Math.max(1, totalImages);
|
|
75
89
|
switch (textureType) {
|
package/dist/parseBasis.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseBasis.js","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parseBasis.js","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"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"}
|
package/dist/parseDds.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { TextureContainer } from '@flighthq/types/contract';
|
|
2
|
+
import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
|
|
3
|
+
export declare function getDdsParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
|
|
2
4
|
export declare function parseDds(bytes: Readonly<Uint8Array>): TextureContainer | null;
|
|
3
5
|
//# sourceMappingURL=parseDds.d.ts.map
|
package/dist/parseDds.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseDds.d.ts","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"parseDds.d.ts","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAKnF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAI/G;AAaD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAE7E"}
|
package/dist/parseDds.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { createByteReader, hasByteReaderBytes, readByteReaderU32, skipByteReader } from './byteReader';
|
|
2
2
|
import { computeTextureContainerLevels } from './textureLevelLayout';
|
|
3
|
-
|
|
3
|
+
export function getDdsParseFailureReason(bytes) {
|
|
4
|
+
const failure = { reason: null };
|
|
5
|
+
const container = parseDdsInternal(bytes, failure);
|
|
6
|
+
return container === null ? failure.reason : null;
|
|
7
|
+
}
|
|
8
|
+
// Parses a DDS container (DirectDraw Bitmap) into a `TextureContainer`, or returns `null` if the bytes
|
|
4
9
|
// are not DDS, are truncated, or carry a pixel format this package does not map (e.g. a legacy 16/24-bit
|
|
5
10
|
// layout, a YUV/luminance format, or a volume texture).
|
|
6
11
|
//
|
|
@@ -12,10 +17,13 @@ import { computeTextureContainerLevels } from './textureLevelLayout';
|
|
|
12
17
|
// `computeTextureContainerLevels`): sub-images are nested layer → face → mip, matching D3D subresource
|
|
13
18
|
// order (a cubemap's 6 faces each hold a full mip chain).
|
|
14
19
|
export function parseDds(bytes) {
|
|
20
|
+
return parseDdsInternal(bytes);
|
|
21
|
+
}
|
|
22
|
+
function parseDdsInternal(bytes, failure) {
|
|
15
23
|
if (!hasDdsMagic(bytes))
|
|
16
|
-
return
|
|
24
|
+
return reject(failure, 'container-unrecognized');
|
|
17
25
|
if (bytes.byteLength < ddsDataOffset)
|
|
18
|
-
return
|
|
26
|
+
return reject(failure, 'header-truncated');
|
|
19
27
|
const reader = createByteReader(bytes, 4);
|
|
20
28
|
skipByteReader(reader, 4); // dwSize
|
|
21
29
|
skipByteReader(reader, 4); // dwFlags
|
|
@@ -34,15 +42,17 @@ export function parseDds(bytes) {
|
|
|
34
42
|
const aMask = readByteReaderU32(reader);
|
|
35
43
|
reader.offset = 112; // dwCaps2
|
|
36
44
|
const caps2 = readByteReaderU32(reader);
|
|
37
|
-
if ((caps2 & ddsCaps2Volume) !== 0 || dwDepth > 1)
|
|
38
|
-
return
|
|
45
|
+
if ((caps2 & ddsCaps2Volume) !== 0 || dwDepth > 1) {
|
|
46
|
+
return reject(failure, 'format-unsupported'); // volume textures not modeled yet
|
|
47
|
+
}
|
|
39
48
|
let format;
|
|
40
49
|
let cube = (caps2 & ddsCaps2Cubemap) !== 0;
|
|
41
50
|
let layers = 1;
|
|
42
51
|
let dataOffset = ddsDataOffset;
|
|
43
52
|
if ((pfFlags & ddsPfFourCC) !== 0 && fourCC === ddsFourCcDx10) {
|
|
44
|
-
if (!hasByteReaderBytes(createByteReader(bytes, ddsDataOffset), 20))
|
|
45
|
-
return
|
|
53
|
+
if (!hasByteReaderBytes(createByteReader(bytes, ddsDataOffset), 20)) {
|
|
54
|
+
return reject(failure, 'header-truncated');
|
|
55
|
+
}
|
|
46
56
|
const dx10 = createByteReader(bytes, ddsDataOffset);
|
|
47
57
|
const dxgiFormat = readByteReaderU32(dx10);
|
|
48
58
|
skipByteReader(dx10, 4); // resourceDimension
|
|
@@ -63,14 +73,15 @@ export function parseDds(bytes) {
|
|
|
63
73
|
format = null;
|
|
64
74
|
}
|
|
65
75
|
if (format === null)
|
|
66
|
-
return
|
|
76
|
+
return reject(failure, 'format-unsupported');
|
|
67
77
|
const width = Math.max(1, dwWidth);
|
|
68
78
|
const height = Math.max(1, dwHeight);
|
|
69
79
|
const faces = cube ? 6 : 1;
|
|
70
80
|
const mipLevels = Math.max(1, dwMipMapCount);
|
|
71
81
|
const layout = computeTextureContainerLevels(format, width, height, mipLevels, layers, faces, dataOffset);
|
|
72
|
-
if (layout === null || layout.endOffset > bytes.byteLength)
|
|
73
|
-
return
|
|
82
|
+
if (layout === null || layout.endOffset > bytes.byteLength) {
|
|
83
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
84
|
+
}
|
|
74
85
|
return {
|
|
75
86
|
depth: 1,
|
|
76
87
|
faces,
|
|
@@ -83,6 +94,11 @@ export function parseDds(bytes) {
|
|
|
83
94
|
width,
|
|
84
95
|
};
|
|
85
96
|
}
|
|
97
|
+
function reject(failure, reason) {
|
|
98
|
+
if (failure !== undefined)
|
|
99
|
+
failure.reason = reason;
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
86
102
|
function hasDdsMagic(bytes) {
|
|
87
103
|
return bytes.byteLength >= 4 && bytes[0] === 0x44 && bytes[1] === 0x44 && bytes[2] === 0x53 && bytes[3] === 0x20;
|
|
88
104
|
}
|
package/dist/parseDds.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseDds.js","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parseDds.js","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,UAAU,wBAAwB,CAAC,KAA2B;IAClE,MAAM,OAAO,GAAiB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnD,OAAO,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,uGAAuG;AACvG,yGAAyG;AACzG,wDAAwD;AACxD,EAAE;AACF,kGAAkG;AAClG,2FAA2F;AAC3F,oGAAoG;AACpG,oGAAoG;AACpG,yFAAyF;AACzF,uGAAuG;AACvG,0DAA0D;AAC1D,MAAM,UAAU,QAAQ,CAAC,KAA2B;IAClD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAA2B,EAAE,OAAsB;IAC3E,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;IAC1E,IAAI,KAAK,CAAC,UAAU,GAAG,aAAa;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAEjF,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1C,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;IACpC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU;IACrC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,sBAAsB;IACjD,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAEhD,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,0BAA0B;IAC9C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAExC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU;IAC/B,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,kCAAkC;IAClF,CAAC;IAED,IAAI,MAAqC,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,UAAU,GAAG,aAAa,CAAC;IAE/B,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC9D,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACpE,OAAO,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC3C,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,oBAAoB;QAC7C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;QAC3C,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAChC,UAAU,GAAG,aAAa,GAAG,EAAE,CAAC;IAClC,CAAC;SAAM,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC3C,CAAC;SAAM,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,kBAAkB,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAElE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,6BAA6B,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC1G,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;QAC3D,OAAO,MAAM,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC;QACR,KAAK;QACL,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS;QACT,gBAAgB,EAAE,MAAM;QACxB,KAAK;KACN,CAAC;AACJ,CAAC;AAMD,SAAS,MAAM,CAAC,OAAiC,EAAE,MAA0C;IAC3F,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B;IAC9C,OAAO,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AACnH,CAAC;AAED,SAAS,kBAAkB,CACzB,WAAmB,EACnB,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa;IAEb,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACjG,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACjG,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wFAAwF;AACxF,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,SAAS;AAC5C,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB,qGAAqG;AACrG,mEAAmE;AACnE,MAAM,aAAa,GAAqD;IACtE,CAAC,EAAE,SAAS;IACZ,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;CACd,CAAC;AAEF,kGAAkG;AAClG,qGAAqG;AACrG,MAAM,eAAe,GAAqD;IACxE,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,UAAU,EAAE,OAAO;IAChC,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,UAAU,EAAE,OAAO;CACjC,CAAC"}
|
package/dist/parseKtx2.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { TextureContainer } from '@flighthq/types/contract';
|
|
2
|
+
import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
|
|
3
|
+
export declare function getKtx2ParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
|
|
2
4
|
export declare function parseKtx2(bytes: Readonly<Uint8Array>): TextureContainer | null;
|
|
3
5
|
//# sourceMappingURL=parseKtx2.d.ts.map
|
package/dist/parseKtx2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseKtx2.d.ts","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"parseKtx2.d.ts","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAWnF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAIhH;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAE9E"}
|
package/dist/parseKtx2.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { createByteReader, hasByteReaderBytes, readByteReaderU32, readByteReaderU64, skipByteReader, } from './byteReader';
|
|
2
|
+
export function getKtx2ParseFailureReason(bytes) {
|
|
3
|
+
const failure = { reason: null };
|
|
4
|
+
const container = parseKtx2Internal(bytes, failure);
|
|
5
|
+
return container === null ? failure.reason : null;
|
|
6
|
+
}
|
|
2
7
|
// Parses a KTX2 container (Khronos KTX 2.0) into a `TextureContainer`, or returns `null` if the bytes
|
|
3
8
|
// are not KTX2, are truncated, or carry a `vkFormat`/supercompression this package does not map yet.
|
|
4
9
|
//
|
|
@@ -12,11 +17,14 @@ import { createByteReader, hasByteReaderBytes, readByteReaderU32, readByteReader
|
|
|
12
17
|
// sub-images and normalized from KTX2's mip-major file order into TextureContainer's canonical
|
|
13
18
|
// layer → face → mip order.
|
|
14
19
|
export function parseKtx2(bytes) {
|
|
20
|
+
return parseKtx2Internal(bytes);
|
|
21
|
+
}
|
|
22
|
+
function parseKtx2Internal(bytes, failure) {
|
|
15
23
|
if (!hasKtx2Identifier(bytes))
|
|
16
|
-
return
|
|
24
|
+
return reject(failure, 'container-unrecognized');
|
|
17
25
|
// 12 id + 68 header/index (17 u32 = 68 bytes) before the level index at offset 80.
|
|
18
26
|
if (bytes.byteLength < ktx2LevelIndexOffset)
|
|
19
|
-
return
|
|
27
|
+
return reject(failure, 'header-truncated');
|
|
20
28
|
const reader = createByteReader(bytes, 12);
|
|
21
29
|
const vkFormat = readByteReaderU32(reader);
|
|
22
30
|
skipByteReader(reader, 4); // typeSize
|
|
@@ -30,10 +38,10 @@ export function parseKtx2(bytes) {
|
|
|
30
38
|
// dfd/kvd/sgd index (2 u32 + 2 u32 + 2 u64 = 32 bytes) — not needed to locate levels.
|
|
31
39
|
const supercompression = ktx2Supercompression[supercompressionScheme];
|
|
32
40
|
if (supercompression === undefined)
|
|
33
|
-
return
|
|
41
|
+
return reject(failure, 'format-unsupported');
|
|
34
42
|
const format = mapKtx2Format(vkFormat, supercompressionScheme);
|
|
35
43
|
if (format === null)
|
|
36
|
-
return
|
|
44
|
+
return reject(failure, 'format-unsupported');
|
|
37
45
|
const width = Math.max(1, pixelWidth);
|
|
38
46
|
const height = Math.max(1, pixelHeight);
|
|
39
47
|
const depth = Math.max(1, pixelDepth);
|
|
@@ -42,7 +50,7 @@ export function parseKtx2(bytes) {
|
|
|
42
50
|
const levelCountPresent = Math.max(1, levelCount);
|
|
43
51
|
reader.offset = ktx2LevelIndexOffset;
|
|
44
52
|
if (!hasByteReaderBytes(reader, levelCountPresent * 24))
|
|
45
|
-
return
|
|
53
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
46
54
|
const fileOrderLevels = [];
|
|
47
55
|
const imagesPerLevel = layers * faces;
|
|
48
56
|
for (let mip = 0; mip < levelCountPresent; mip += 1) {
|
|
@@ -50,7 +58,7 @@ export function parseKtx2(bytes) {
|
|
|
50
58
|
const byteLength = readByteReaderU64(reader);
|
|
51
59
|
skipByteReader(reader, 8); // uncompressedByteLength
|
|
52
60
|
if (byteOffset + byteLength > bytes.byteLength)
|
|
53
|
-
return
|
|
61
|
+
return reject(failure, 'level-range-out-of-bounds');
|
|
54
62
|
const mipWidth = Math.max(1, width >> mip);
|
|
55
63
|
const mipHeight = Math.max(1, height >> mip);
|
|
56
64
|
const splittable = supercompression === 'None' && imagesPerLevel > 1 && byteLength % imagesPerLevel === 0;
|
|
@@ -91,6 +99,11 @@ export function parseKtx2(bytes) {
|
|
|
91
99
|
width,
|
|
92
100
|
};
|
|
93
101
|
}
|
|
102
|
+
function reject(failure, reason) {
|
|
103
|
+
if (failure !== undefined)
|
|
104
|
+
failure.reason = reason;
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
94
107
|
function hasKtx2Identifier(bytes) {
|
|
95
108
|
if (bytes.byteLength < 12)
|
|
96
109
|
return false;
|
package/dist/parseKtx2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseKtx2.js","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parseKtx2.js","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,MAAM,UAAU,yBAAyB,CAAC,KAA2B;IACnE,MAAM,OAAO,GAAiB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,sGAAsG;AACtG,qGAAqG;AACrG,EAAE;AACF,uGAAuG;AACvG,sGAAsG;AACtG,8FAA8F;AAC9F,oGAAoG;AACpG,qGAAqG;AACrG,qGAAqG;AACrG,kGAAkG;AAClG,+FAA+F;AAC/F,4BAA4B;AAC5B,MAAM,UAAU,SAAS,CAAC,KAA2B;IACnD,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAC,KAA2B,EAAE,OAAsB;IAC5E,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;IAEhF,mFAAmF;IACnF,IAAI,KAAK,CAAC,UAAU,GAAG,oBAAoB;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAExF,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC3C,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW;IACtC,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzD,sFAAsF;IAEtF,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;IACtE,IAAI,gBAAgB,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAEjF,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IAC/D,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAElE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAElD,MAAM,CAAC,MAAM,GAAG,oBAAoB,CAAC;IACrC,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,EAAE,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;IAE7G,MAAM,eAAe,GAA4B,EAAE,CAAC;IACpD,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAC;IACtC,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC7C,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,yBAAyB;QACpD,IAAI,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC,UAAU;YAAE,OAAO,MAAM,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;QAEpG,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,IAAI,GAAG,CAAC,CAAC;QAE7C,MAAM,UAAU,GAAG,gBAAgB,KAAK,MAAM,IAAI,cAAc,GAAG,CAAC,IAAI,UAAU,GAAG,cAAc,KAAK,CAAC,CAAC;QAC1G,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,eAAe,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACrF,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC;QAC9C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,cAAc,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACvD,eAAe,CAAC,IAAI,CAAC;gBACnB,UAAU,EAAE,SAAS;gBACrB,UAAU,EAAE,UAAU,GAAG,KAAK,GAAG,SAAS;gBAC1C,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM,GAAG,eAAe,CAAC;IAC7B,IACE,gBAAgB,KAAK,MAAM;QAC3B,cAAc,GAAG,CAAC;QAClB,eAAe,CAAC,MAAM,KAAK,iBAAiB,GAAG,cAAc,EAC7D,CAAC;QACD,MAAM,GAAG,EAAE,CAAC;QACZ,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,cAAc,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACvD,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;gBACpD,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,GAAG,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK;QACL,KAAK;QACL,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,SAAS,EAAE,iBAAiB;QAC5B,gBAAgB;QAChB,KAAK;KACN,CAAC;AACJ,CAAC;AAMD,SAAS,MAAM,CAAC,OAAiC,EAAE,MAA0C;IAC3F,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,KAA2B;IACpD,IAAI,KAAK,CAAC,UAAU,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACnD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB,EAAE,sBAA8B;IACrE,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,sBAAsB,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC5E,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,qBAAqB;AACrB,MAAM,cAAc,GAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEnH,wFAAwF;AACxF,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,MAAM,oBAAoB,GAA+D;IACvF,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,MAAM;CACV,CAAC;AAEF,6GAA6G;AAC7G,yGAAyG;AACzG,mGAAmG;AACnG,MAAM,YAAY,GAAqD;IACrE,CAAC,EAAE,SAAS;IACZ,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,SAAS;IACb,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;CACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/texture-formats",
|
|
3
|
-
"version": "0.3.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"author": "Joshua Granick and other contributors",
|
|
5
|
+
"license": "MIT",
|
|
4
6
|
"repository": {
|
|
5
7
|
"type": "git",
|
|
6
8
|
"url": "https://github.com/flighthq/flight.git",
|
|
@@ -36,7 +38,7 @@
|
|
|
36
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
37
39
|
},
|
|
38
40
|
"dependencies": {
|
|
39
|
-
"@flighthq/types": "0.3.0
|
|
41
|
+
"@flighthq/types": "0.3.0"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
44
|
"typescript": "^5.3.0"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { explainTextureContainerParse } from './explainTextureContainerParse';
|
|
2
|
+
|
|
3
|
+
describe('explainTextureContainerParse', () => {
|
|
4
|
+
it('reports an unrecognized container', () => {
|
|
5
|
+
expect(explainTextureContainerParse(new Uint8Array([0, 1, 2, 3]))).toEqual({
|
|
6
|
+
container: null,
|
|
7
|
+
reason: 'container-unrecognized',
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it.each([
|
|
12
|
+
['atf', new Uint8Array([0x41, 0x54, 0x46])],
|
|
13
|
+
['basis', new Uint8Array([0x73, 0x42])],
|
|
14
|
+
['dds', new Uint8Array([0x44, 0x44, 0x53, 0x20])],
|
|
15
|
+
['ktx2', new Uint8Array(ktx2Identifier)],
|
|
16
|
+
] as const)('reports a truncated %s header', (container, bytes) => {
|
|
17
|
+
expect(explainTextureContainerParse(bytes)).toEqual({ container, reason: 'header-truncated' });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('distinguishes unsupported formats from invalid structures', () => {
|
|
21
|
+
expect(explainTextureContainerParse(createKtx2({ vkFormat: 999 }))).toEqual({
|
|
22
|
+
container: 'ktx2',
|
|
23
|
+
reason: 'format-unsupported',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const basis = new Uint8Array(67);
|
|
27
|
+
basis.set([0x73, 0x42]);
|
|
28
|
+
expect(explainTextureContainerParse(basis)).toEqual({
|
|
29
|
+
container: 'basis',
|
|
30
|
+
reason: 'structure-invalid',
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('reports a level range that overruns the bytes', () => {
|
|
35
|
+
expect(explainTextureContainerParse(createKtx2({ byteLength: 8 }))).toEqual({
|
|
36
|
+
container: 'ktx2',
|
|
37
|
+
reason: 'level-range-out-of-bounds',
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('returns null when the detected container parses', () => {
|
|
42
|
+
expect(explainTextureContainerParse(createKtx2({ byteLength: 1, payloadBytes: 1 }))).toBeNull();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function createKtx2(options: {
|
|
47
|
+
readonly byteLength?: number;
|
|
48
|
+
readonly payloadBytes?: number;
|
|
49
|
+
readonly vkFormat?: number;
|
|
50
|
+
}) {
|
|
51
|
+
const bytes = new Uint8Array(104 + (options.payloadBytes ?? 0));
|
|
52
|
+
bytes.set(ktx2Identifier);
|
|
53
|
+
const view = new DataView(bytes.buffer);
|
|
54
|
+
view.setUint32(12, options.vkFormat ?? 37, true);
|
|
55
|
+
view.setUint32(20, 1, true); // pixelWidth
|
|
56
|
+
view.setUint32(24, 1, true); // pixelHeight
|
|
57
|
+
view.setUint32(36, 1, true); // faceCount
|
|
58
|
+
view.setUint32(40, 1, true); // levelCount
|
|
59
|
+
view.setUint32(80, 104, true); // level byteOffset, low u32 of u64
|
|
60
|
+
view.setUint32(88, options.byteLength ?? 0, true); // level byteLength, low u32 of u64
|
|
61
|
+
view.setUint32(96, options.byteLength ?? 0, true); // uncompressedByteLength, low u32 of u64
|
|
62
|
+
return bytes;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const ktx2Identifier: readonly number[] = [0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a];
|
package/src/parseAtf.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TextureContainer } from '@flighthq/types/contract';
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { parseAtf } from './parseAtf';
|
|
4
|
+
import { getAtfParseFailureReason, parseAtf } from './parseAtf';
|
|
5
5
|
import { selectTextureContainer } from './selectTextureContainer';
|
|
6
6
|
|
|
7
7
|
interface AtfOptions {
|
|
@@ -80,6 +80,12 @@ function expectLevelRangesInBounds(containers: readonly TextureContainer[], byte
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
describe('getAtfParseFailureReason', () => {
|
|
84
|
+
it('reports a truncated detected header', () => {
|
|
85
|
+
expect(getAtfParseFailureReason(new Uint8Array([0x41, 0x54, 0x46]))).toBe('header-truncated');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
83
89
|
describe('parseAtf', () => {
|
|
84
90
|
it('parses a cross-platform ATF as one peer container per populated GPU-format slot', () => {
|
|
85
91
|
// Version 3, format 5 (RAW_COMPRESSED_ALPHA), 8x8, 3 mips, all four slots populated.
|
package/src/parseBasis.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { parseBasis } from './parseBasis';
|
|
3
|
+
import { getBasisParseFailureReason, parseBasis } from './parseBasis';
|
|
4
4
|
|
|
5
5
|
interface BasisSlice {
|
|
6
6
|
imageIndex: number;
|
|
@@ -54,6 +54,12 @@ function buildBasis(opts: BasisOptions): Uint8Array {
|
|
|
54
54
|
return bytes;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
describe('getBasisParseFailureReason', () => {
|
|
58
|
+
it('reports a truncated detected header', () => {
|
|
59
|
+
expect(getBasisParseFailureReason(new Uint8Array([0x73, 0x42]))).toBe('header-truncated');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
57
63
|
describe('parseBasis', () => {
|
|
58
64
|
it('parses a single-slice ETC1S image', () => {
|
|
59
65
|
const container = parseBasis(
|
package/src/parseDds.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { parseDds } from './parseDds';
|
|
3
|
+
import { getDdsParseFailureReason, parseDds } from './parseDds';
|
|
4
4
|
|
|
5
5
|
function fourCC(text: string): number {
|
|
6
6
|
return (
|
|
@@ -66,6 +66,12 @@ function buildDds(opts: DdsOptions): Uint8Array {
|
|
|
66
66
|
return bytes;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
describe('getDdsParseFailureReason', () => {
|
|
70
|
+
it('reports a truncated detected header', () => {
|
|
71
|
+
expect(getDdsParseFailureReason(new Uint8Array([0x44, 0x44, 0x53, 0x20]))).toBe('header-truncated');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
69
75
|
describe('parseDds', () => {
|
|
70
76
|
it('parses a single-mip BC1 (DXT1) texture', () => {
|
|
71
77
|
const container = parseDds(buildDds({ fourCC: fourCC('DXT1'), height: 4, pfFlags: 0x4, width: 4 }));
|
package/src/parseKtx2.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { parseKtx2 } from './parseKtx2';
|
|
3
|
+
import { getKtx2ParseFailureReason, parseKtx2 } from './parseKtx2';
|
|
4
4
|
|
|
5
5
|
const ktx2Magic = [0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
6
6
|
|
|
@@ -46,6 +46,12 @@ function buildKtx2(opts: Ktx2Options): Uint8Array {
|
|
|
46
46
|
return bytes;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
describe('getKtx2ParseFailureReason', () => {
|
|
50
|
+
it('reports a truncated detected header', () => {
|
|
51
|
+
expect(getKtx2ParseFailureReason(new Uint8Array(ktx2Magic))).toBe('header-truncated');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
49
55
|
describe('parseKtx2', () => {
|
|
50
56
|
it('parses a single-mip uncompressed 2D texture', () => {
|
|
51
57
|
const container = parseKtx2(
|