public static KtxFile Load(File file, bool readKeyValuePairs) { KtxHeader header = ReadStruct <KtxHeader>(file); KtxKeyValuePair[] kvps = null; if (readKeyValuePairs) { int keyValuePairBytesRead = 0; List <KtxKeyValuePair> keyValuePairs = new List <KtxKeyValuePair>(); while (keyValuePairBytesRead < header.BytesOfKeyValueData) { int bytesRemaining = (int)(header.BytesOfKeyValueData - keyValuePairBytesRead); KtxKeyValuePair kvp = ReadNextKeyValuePair(file, out int read); keyValuePairBytesRead += read; keyValuePairs.Add(kvp); } kvps = keyValuePairs.ToArray(); } else { file.Skip((int)header.BytesOfKeyValueData); // Skip over header data. } uint numberOfMipmapLevels = Math.Max(1, header.NumberOfMipmapLevels); uint numberOfArrayElements = Math.Max(1, header.NumberOfArrayElements); uint numberOfFaces = Math.Max(1, header.NumberOfFaces); uint baseWidth = Math.Max(1, header.PixelWidth); uint baseHeight = Math.Max(1, header.PixelHeight); uint baseDepth = Math.Max(1, header.PixelDepth); List <uint> imageSizes = new List <uint>(); MipmapLevel[] images = new MipmapLevel[numberOfMipmapLevels]; long dataSize = file.Length - file.Position; uint totalSize = 0; for (int mip = 0; mip < numberOfMipmapLevels; mip++) { uint mipWidth = Math.Max(1, baseWidth / (uint)(Math.Pow(2, mip))); uint mipHeight = Math.Max(1, baseHeight / (uint)(Math.Pow(2, mip))); uint mipDepth = Math.Max(1, baseDepth / (uint)(Math.Pow(2, mip))); uint imageSize = file.Read <uint>(); if (mip == 11) { //bug? imageSize = Math.Min(imageSizes.Back() >> 2, imageSize); //imageSize = 1; } imageSizes.Add(imageSize); ArrayElement[] arrayElements = new ArrayElement[numberOfArrayElements]; bool isCubemap = header.NumberOfFaces == 6 && header.NumberOfArrayElements == 0; uint arrayElementSize = imageSize / numberOfArrayElements; for (int arr = 0; arr < numberOfArrayElements; arr++) { uint faceSize = arrayElementSize; ImageFace[] faces = new ImageFace[numberOfFaces]; for (int face = 0; face < numberOfFaces; face++) { faces[face] = new ImageFace(file.ReadBytes((int)faceSize)); uint cubePadding = 0u; if (isCubemap) { cubePadding = 3 - ((imageSize + 3) % 4); } file.Skip((int)cubePadding); totalSize += faceSize; } arrayElements[arr] = new ArrayElement(faces); } images[mip] = new MipmapLevel( mipWidth, mipHeight, mipDepth, imageSize, arrayElements, header.NumberOfArrayElements); uint mipPaddingBytes = 3 - ((imageSize + 3) % 4); //Debug.Assert(mipPaddingBytes == 0); file.Skip((int)mipPaddingBytes); } //Debug.Assert(dataSize == numberOfMipmapLevels * 4 + totalSize); return(new KtxFile(header, kvps, images)); }
public KtxFile(KtxHeader header, KtxKeyValuePair[] keyValuePairs, MipmapLevel[] mipmaps) { Header = header; KeyValuePairs = keyValuePairs; Mipmaps = mipmaps; }