{"version":3,"file":"parseKTX.mjs","sources":["../../src/parsers/parseKTX.ts"],"sourcesContent":["import { BufferResource, FORMATS, TYPES } from 'pixijs/core';\nimport { INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from '../const';\nimport { CompressedTextureResource } from '../resources';\n\nimport type { CompressedLevelBuffer } from '../resources';\n\n/**\n * The 12-byte KTX file identifier\n * @see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/#2.1\n * @ignore\n */\nconst FILE_IDENTIFIER = [0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A];\n\n/**\n * The value stored in the \"endianness\" field.\n * @see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/#2.2\n * @ignore\n */\nconst ENDIANNESS = 0x04030201;\n\n/**\n * Byte offsets of the KTX file header fields\n * @ignore\n */\nconst KTX_FIELDS = {\n    FILE_IDENTIFIER: 0,\n    ENDIANNESS: 12,\n    GL_TYPE: 16,\n    GL_TYPE_SIZE: 20,\n    GL_FORMAT: 24,\n    GL_INTERNAL_FORMAT: 28,\n    GL_BASE_INTERNAL_FORMAT: 32,\n    PIXEL_WIDTH: 36,\n    PIXEL_HEIGHT: 40,\n    PIXEL_DEPTH: 44,\n    NUMBER_OF_ARRAY_ELEMENTS: 48,\n    NUMBER_OF_FACES: 52,\n    NUMBER_OF_MIPMAP_LEVELS: 56,\n    BYTES_OF_KEY_VALUE_DATA: 60\n};\n\n/**\n * Byte size of the file header fields in {@code KTX_FIELDS}\n * @ignore\n */\nconst FILE_HEADER_SIZE = 64;\n\n/**\n * Maps {@link PIXI.TYPES} to the bytes taken per component, excluding those ones that are bit-fields.\n * @ignore\n */\nexport const TYPES_TO_BYTES_PER_COMPONENT: { [id: number]: number } = {\n    [TYPES.UNSIGNED_BYTE]: 1,\n    [TYPES.UNSIGNED_SHORT]: 2,\n    [TYPES.INT]: 4,\n    [TYPES.UNSIGNED_INT]: 4,\n    [TYPES.FLOAT]: 4,\n    [TYPES.HALF_FLOAT]: 8\n};\n\n/**\n * Number of components in each {@link PIXI.FORMATS}\n * @ignore\n */\nexport const FORMATS_TO_COMPONENTS: { [id: number]: number } = {\n    [FORMATS.RGBA]: 4,\n    [FORMATS.RGB]: 3,\n    [FORMATS.RG]: 2,\n    [FORMATS.RED]: 1,\n    [FORMATS.LUMINANCE]: 1,\n    [FORMATS.LUMINANCE_ALPHA]: 2,\n    [FORMATS.ALPHA]: 1\n};\n\n/**\n * Number of bytes per pixel in bit-field types in {@link PIXI.TYPES}\n * @ignore\n */\nexport const TYPES_TO_BYTES_PER_PIXEL: { [id: number]: number } = {\n    [TYPES.UNSIGNED_SHORT_4_4_4_4]: 2,\n    [TYPES.UNSIGNED_SHORT_5_5_5_1]: 2,\n    [TYPES.UNSIGNED_SHORT_5_6_5]: 2\n};\n\nexport function parseKTX(url: string, arrayBuffer: ArrayBuffer, loadKeyValueData = false): {\n    compressed?: CompressedTextureResource[]\n    uncompressed?: { resource: BufferResource, type: TYPES, format: FORMATS }[]\n    kvData: Map<string, DataView> | null\n}\n{\n    const dataView = new DataView(arrayBuffer);\n\n    if (!validate(url, dataView))\n    {\n        return null;\n    }\n\n    const littleEndian = dataView.getUint32(KTX_FIELDS.ENDIANNESS, true) === ENDIANNESS;\n    const glType = dataView.getUint32(KTX_FIELDS.GL_TYPE, littleEndian);\n    // const glTypeSize = dataView.getUint32(KTX_FIELDS.GL_TYPE_SIZE, littleEndian);\n    const glFormat = dataView.getUint32(KTX_FIELDS.GL_FORMAT, littleEndian);\n    const glInternalFormat = dataView.getUint32(KTX_FIELDS.GL_INTERNAL_FORMAT, littleEndian);\n    const pixelWidth = dataView.getUint32(KTX_FIELDS.PIXEL_WIDTH, littleEndian);\n    const pixelHeight = dataView.getUint32(KTX_FIELDS.PIXEL_HEIGHT, littleEndian) || 1;// \"pixelHeight = 0\" -> \"1\"\n    const pixelDepth = dataView.getUint32(KTX_FIELDS.PIXEL_DEPTH, littleEndian) || 1;// ^^\n    const numberOfArrayElements = dataView.getUint32(KTX_FIELDS.NUMBER_OF_ARRAY_ELEMENTS, littleEndian) || 1;// ^^\n    const numberOfFaces = dataView.getUint32(KTX_FIELDS.NUMBER_OF_FACES, littleEndian);\n    const numberOfMipmapLevels = dataView.getUint32(KTX_FIELDS.NUMBER_OF_MIPMAP_LEVELS, littleEndian);\n    const bytesOfKeyValueData = dataView.getUint32(KTX_FIELDS.BYTES_OF_KEY_VALUE_DATA, littleEndian);\n\n    // Whether the platform architecture is little endian. If littleEndian !== platformLittleEndian, then the\n    // file contents must be endian-converted!\n    // TODO: Endianness conversion\n    // const platformLittleEndian = new Uint8Array((new Uint32Array([ENDIANNESS])).buffer)[0] === 0x01;\n\n    if (pixelHeight === 0 || pixelDepth !== 1)\n    {\n        throw new Error('Only 2D textures are supported');\n    }\n    if (numberOfFaces !== 1)\n    {\n        throw new Error('CubeTextures are not supported by KTXLoader yet!');\n    }\n    if (numberOfArrayElements !== 1)\n    {\n        // TODO: Support splitting array-textures into multiple BaseTextures\n        throw new Error('WebGL does not support array textures');\n    }\n\n    // TODO: 8x4 blocks for 2bpp pvrtc\n    const blockWidth = 4;\n    const blockHeight = 4;\n\n    const alignedWidth = (pixelWidth + 3) & ~3;\n    const alignedHeight = (pixelHeight + 3) & ~3;\n    const imageBuffers = new Array<CompressedLevelBuffer[]>(numberOfArrayElements);\n    let imagePixels = pixelWidth * pixelHeight;\n\n    if (glType === 0)\n    {\n        // Align to 16 pixels (4x4 blocks)\n        imagePixels = alignedWidth * alignedHeight;\n    }\n\n    let imagePixelByteSize: number;\n\n    if (glType !== 0)\n    {\n        // Uncompressed texture format\n        if (TYPES_TO_BYTES_PER_COMPONENT[glType])\n        {\n            imagePixelByteSize = TYPES_TO_BYTES_PER_COMPONENT[glType] * FORMATS_TO_COMPONENTS[glFormat];\n        }\n        else\n        {\n            imagePixelByteSize = TYPES_TO_BYTES_PER_PIXEL[glType];\n        }\n    }\n    else\n    {\n        imagePixelByteSize = INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[glInternalFormat];\n    }\n\n    if (imagePixelByteSize === undefined)\n    {\n        throw new Error('Unable to resolve the pixel format stored in the *.ktx file!');\n    }\n\n    const kvData: Map<string, DataView> | null = loadKeyValueData\n        ? parseKvData(dataView, bytesOfKeyValueData, littleEndian)\n        : null;\n\n    const imageByteSize = imagePixels * imagePixelByteSize;\n    let mipByteSize = imageByteSize;\n    let mipWidth = pixelWidth;\n    let mipHeight = pixelHeight;\n    let alignedMipWidth = alignedWidth;\n    let alignedMipHeight = alignedHeight;\n    let imageOffset = FILE_HEADER_SIZE + bytesOfKeyValueData;\n\n    for (let mipmapLevel = 0; mipmapLevel < numberOfMipmapLevels; mipmapLevel++)\n    {\n        const imageSize = dataView.getUint32(imageOffset, littleEndian);\n        let elementOffset = imageOffset + 4;\n\n        for (let arrayElement = 0; arrayElement < numberOfArrayElements; arrayElement++)\n        {\n            // TODO: Maybe support 3D textures? :-)\n            // for (let zSlice = 0; zSlice < pixelDepth; zSlice)\n\n            let mips = imageBuffers[arrayElement];\n\n            if (!mips)\n            {\n                mips = imageBuffers[arrayElement] = new Array(numberOfMipmapLevels);\n            }\n\n            mips[mipmapLevel] = {\n                levelID: mipmapLevel,\n\n                // don't align mipWidth when texture not compressed! (glType not zero)\n                levelWidth: numberOfMipmapLevels > 1 || glType !== 0 ? mipWidth : alignedMipWidth,\n                levelHeight: numberOfMipmapLevels > 1 || glType !== 0 ? mipHeight : alignedMipHeight,\n                levelBuffer: new Uint8Array(arrayBuffer, elementOffset, mipByteSize)\n            };\n            elementOffset += mipByteSize;\n        }\n\n        // HINT: Aligns to 4-byte boundary after jumping imageSize (in lieu of mipPadding)\n        imageOffset += imageSize + 4;// (+4 to jump the imageSize field itself)\n        imageOffset = imageOffset % 4 !== 0 ? imageOffset + 4 - (imageOffset % 4) : imageOffset;\n\n        // Calculate mipWidth, mipHeight for _next_ iteration\n        mipWidth = (mipWidth >> 1) || 1;\n        mipHeight = (mipHeight >> 1) || 1;\n        alignedMipWidth = (mipWidth + blockWidth - 1) & ~(blockWidth - 1);\n        alignedMipHeight = (mipHeight + blockHeight - 1) & ~(blockHeight - 1);\n\n        // Each mipmap level is 4-times smaller?\n        mipByteSize = alignedMipWidth * alignedMipHeight * imagePixelByteSize;\n    }\n\n    // We use the levelBuffers feature of CompressedTextureResource b/c texture data is image-major, not level-major.\n    if (glType !== 0)\n    {\n        return {\n            uncompressed: imageBuffers.map((levelBuffers) =>\n            {\n                let buffer: Float32Array | Uint32Array | Int32Array | Uint8Array = levelBuffers[0].levelBuffer;\n                let convertToInt = false;\n\n                if (glType === TYPES.FLOAT)\n                {\n                    buffer = new Float32Array(\n                        levelBuffers[0].levelBuffer.buffer,\n                        levelBuffers[0].levelBuffer.byteOffset,\n                        levelBuffers[0].levelBuffer.byteLength / 4);\n                }\n                else if (glType === TYPES.UNSIGNED_INT)\n                {\n                    convertToInt = true;\n                    buffer = new Uint32Array(\n                        levelBuffers[0].levelBuffer.buffer,\n                        levelBuffers[0].levelBuffer.byteOffset,\n                        levelBuffers[0].levelBuffer.byteLength / 4);\n                }\n                else if (glType === TYPES.INT)\n                {\n                    convertToInt = true;\n                    buffer = new Int32Array(\n                        levelBuffers[0].levelBuffer.buffer,\n                        levelBuffers[0].levelBuffer.byteOffset,\n                        levelBuffers[0].levelBuffer.byteLength / 4);\n                }\n\n                return {\n                    resource: new BufferResource(\n                        buffer,\n                        {\n                            width: levelBuffers[0].levelWidth,\n                            height: levelBuffers[0].levelHeight,\n                        }\n                    ),\n                    type: glType,\n                    format: convertToInt ? convertFormatToInteger(glFormat) : glFormat,\n                };\n            }),\n            kvData\n        };\n    }\n\n    return {\n        compressed: imageBuffers.map((levelBuffers) => new CompressedTextureResource(null, {\n            format: glInternalFormat,\n            width: pixelWidth,\n            height: pixelHeight,\n            levels: numberOfMipmapLevels,\n            levelBuffers,\n        })),\n        kvData\n    };\n}\n\n/**\n * Checks whether the arrayBuffer contains a valid *.ktx file.\n * @param url\n * @param dataView\n */\nfunction validate(url: string, dataView: DataView): boolean\n{\n    // NOTE: Do not optimize this into 3 32-bit integer comparison because the endianness\n    // of the data is not specified.\n    for (let i = 0; i < FILE_IDENTIFIER.length; i++)\n    {\n        if (dataView.getUint8(i) !== FILE_IDENTIFIER[i])\n        {\n            // #if _DEBUG\n            console.error(`${url} is not a valid *.ktx file!`);\n            // #endif\n\n            return false;\n        }\n    }\n\n    return true;\n}\n\nfunction convertFormatToInteger(format: FORMATS)\n{\n    switch (format)\n    {\n        case FORMATS.RGBA: return FORMATS.RGBA_INTEGER;\n        case FORMATS.RGB: return FORMATS.RGB_INTEGER;\n        case FORMATS.RG: return FORMATS.RG_INTEGER;\n        case FORMATS.RED: return FORMATS.RED_INTEGER;\n        default: return format;\n    }\n}\n\nfunction parseKvData(dataView: DataView, bytesOfKeyValueData: number, littleEndian: boolean): Map<string, DataView>\n{\n    const kvData = new Map<string, DataView>();\n    let bytesIntoKeyValueData = 0;\n\n    while (bytesIntoKeyValueData < bytesOfKeyValueData)\n    {\n        const keyAndValueByteSize = dataView.getUint32(FILE_HEADER_SIZE + bytesIntoKeyValueData, littleEndian);\n        const keyAndValueByteOffset = FILE_HEADER_SIZE + bytesIntoKeyValueData + 4;\n        const valuePadding = 3 - ((keyAndValueByteSize + 3) % 4);\n\n        // Bounds check\n        if (keyAndValueByteSize === 0 || keyAndValueByteSize > bytesOfKeyValueData - bytesIntoKeyValueData)\n        {\n            console.error('KTXLoader: keyAndValueByteSize out of bounds');\n            break;\n        }\n\n        // Note: keyNulByte can't be 0 otherwise the key is an empty string.\n        let keyNulByte = 0;\n\n        for (; keyNulByte < keyAndValueByteSize; keyNulByte++)\n        {\n            if (dataView.getUint8(keyAndValueByteOffset + keyNulByte) === 0x00)\n            {\n                break;\n            }\n        }\n\n        if (keyNulByte === -1)\n        {\n            console.error('KTXLoader: Failed to find null byte terminating kvData key');\n            break;\n        }\n\n        const key = new TextDecoder().decode(\n            new Uint8Array(dataView.buffer, keyAndValueByteOffset, keyNulByte)\n        );\n        const value = new DataView(\n            dataView.buffer,\n            keyAndValueByteOffset + keyNulByte + 1,\n            keyAndValueByteSize - keyNulByte - 1,\n        );\n\n        kvData.set(key, value);\n\n        // 4 = the keyAndValueByteSize field itself\n        // keyAndValueByteSize = the bytes taken by the key and value\n        // valuePadding = extra padding to align with 4 bytes\n        bytesIntoKeyValueData += 4 + keyAndValueByteSize + valuePadding;\n    }\n\n    return kvData;\n}\n"],"names":[],"mappings":"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"}