Ejemplo n.º 1
0
        /// <summary>
        /// Loads a KTX file from a stream.
        /// </summary>
        public static KtxFile Load(Stream s)
        {
            using (BinaryReader br = new BinaryReader(s, UTF8, true))
            {
                KtxHeader header = br.ReadStruct <KtxHeader>();

                if (header.NumberOfArrayElements > 0)
                {
                    throw new NotSupportedException("KTX files with arrays are not supported.");
                }

                KtxFile ktx = new KtxFile(header);

                int keyValuePairBytesRead = 0;
                while (keyValuePairBytesRead < header.BytesOfKeyValueData)
                {
                    KtxKeyValuePair kvp = KtxKeyValuePair.ReadKeyValuePair(br, out int read);
                    keyValuePairBytesRead += read;
                    ktx.KeyValuePairs.Add(kvp);
                }

                uint numberOfFaces = Math.Max(1, header.NumberOfFaces);
                ktx.MipMaps.Capacity = (int)header.NumberOfMipmapLevels;
                for (uint mipLevel = 0; mipLevel < header.NumberOfMipmapLevels; mipLevel++)
                {
                    uint imageSize = br.ReadUInt32();
                    uint mipWidth  = header.PixelWidth / (uint)(Math.Pow(2, mipLevel));
                    uint mipHeight = header.PixelHeight / (uint)(Math.Pow(2, mipLevel));

                    ktx.MipMaps.Add(new KtxMipmap(imageSize, mipWidth, mipHeight, numberOfFaces));

                    bool cubemap = header.NumberOfFaces > 1 && header.NumberOfArrayElements == 0;
                    for (uint face = 0; face < numberOfFaces; face++)
                    {
                        byte[] faceData = br.ReadBytes((int)imageSize);
                        ktx.MipMaps[(int)mipLevel].Faces[(int)face] = new KtxMipFace(faceData, mipWidth, mipHeight);
                        if (cubemap)
                        {
                            uint cubePadding = 0u;
                            cubePadding = 3 - ((imageSize + 3) % 4);
                            br.SkipPadding(cubePadding);
                        }
                    }

                    uint mipPaddingBytes = 3 - ((imageSize + 3) % 4);
                    br.SkipPadding(mipPaddingBytes);
                }

                return(ktx);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Writes this ktx file into a stream.
        /// </summary>
        public void Write(Stream s)
        {
            if (MipMaps.Count < 1 || MipMaps[0].NumberOfFaces < 1)
            {
                throw new InvalidOperationException("The KTX structure should have at least 1 mipmap level and 1 Face before writing to file.");
            }

            using (BinaryWriter bw = new BinaryWriter(s, UTF8, true))
            {
                uint bytesOfKeyValueData = (uint)KeyValuePairs.Sum(x => x.GetSizeWithPadding());

                Header.BytesOfKeyValueData   = bytesOfKeyValueData;
                Header.NumberOfFaces         = MipMaps[0].NumberOfFaces;
                Header.NumberOfMipmapLevels  = (uint)MipMaps.Count;
                Header.NumberOfArrayElements = 0;

                if (!Header.VerifyHeader())
                {
                    throw new InvalidOperationException("Please verify the header validity before writing to file.");
                }

                bw.WriteStruct(Header);

                foreach (KtxKeyValuePair keyValuePair in KeyValuePairs)
                {
                    KtxKeyValuePair.WriteKeyValuePair(bw, keyValuePair);
                }

                for (int mip = 0; mip < Header.NumberOfMipmapLevels; mip++)
                {
                    uint imageSize = MipMaps[mip].SizeInBytes;
                    bw.Write(imageSize);
                    bool isCubemap = Header.NumberOfFaces == 6 && Header.NumberOfArrayElements == 0;
                    for (int f = 0; f < Header.NumberOfFaces; f++)
                    {
                        bw.Write(MipMaps[mip].Faces[f].Data);
                        uint cubePadding = 0u;
                        if (isCubemap)
                        {
                            cubePadding = 3 - ((imageSize + 3) % 4);
                        }
                        bw.AddPadding(cubePadding);
                    }

                    uint mipPaddingBytes = 3 - ((imageSize + 3) % 4);
                    bw.AddPadding(mipPaddingBytes);
                }
            }
        }
Ejemplo n.º 3
0
        public static uint WriteKeyValuePair(BinaryWriter bw, KtxKeyValuePair pair)
        {
            int         keySpanLength = UTF8.GetByteCount(pair.Key);
            Span <byte> keySpan       = stackalloc byte[keySpanLength];
            Span <byte> valueSpan     = pair.Value;

            uint totalSize    = (uint)(keySpan.Length + 1 + valueSpan.Length);
            int  paddingBytes = (int)(3 - ((totalSize + 3) % 4));

            bw.Write(totalSize);
            bw.Write(keySpan);
            bw.Write((byte)0);
            bw.Write(valueSpan);

            return((uint)(totalSize + paddingBytes));
        }