예제 #1
0
        /// <summary>
        /// KtxHeader constructor
        /// </summary>
        /// <param name="stream">Stream for reading</param>
        public KtxHeader(Stream stream)
        {
            // Skip first 12 bytes since they only contain identifier
            stream.Seek(12, SeekOrigin.Begin);

            // Read endianness as bytes
            byte[] endiannessBytes = new byte[4];
            int    bytesRead       = stream.Read(buffer: endiannessBytes, offset: 0, count: endiannessBytes.Length);

            if (bytesRead != 4)
            {
                throw new InvalidOperationException("Cannot read enough bytes from stream!");
            }

            if (!Common.littleEndianAsBytes.SequenceEqual(endiannessBytes) && !Common.bigEndianAsBytes.SequenceEqual(endiannessBytes))
            {
                throw new InvalidOperationException("Endianness info in header is not valid!");
            }

            this.isInputLittleEndian = Common.littleEndianAsBytes.SequenceEqual(endiannessBytes);

            // Turn endianness as bytes to uint
            this.endiannessValue = BitConverter.ToUInt32(endiannessBytes, 0);

            // See if following uint reads need endian swap
            bool shouldSwapEndianness = (this.endiannessValue != Common.expectedEndianValue);

            // Use the stream in a binary reader.
            using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true))
            {
                // Swap endianness for every KTX variable if needed

                this.glTypeAsUint = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();
                if (GlDataType.IsDefined(typeof(GlDataType), this.glTypeAsUint))
                {
                    this.glDataType = (GlDataType)this.glTypeAsUint;
                }
                else
                {
                    this.glDataType = GlDataType.NotKnown;
                }

                this.glTypeSizeAsUint = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.glFormatAsUint = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();
                if (GlPixelFormat.IsDefined(typeof(GlPixelFormat), this.glFormatAsUint))
                {
                    this.glFormat = (GlPixelFormat)this.glFormatAsUint;
                }
                else
                {
                    this.glFormat = GlPixelFormat.NotKnown;
                }

                this.glInternalFormatAsUint = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();
                if (GlInternalFormat.IsDefined(typeof(GlInternalFormat), this.glInternalFormatAsUint))
                {
                    this.glInternalFormat = (GlInternalFormat)this.glInternalFormatAsUint;
                }
                else
                {
                    this.glInternalFormat = GlInternalFormat.NotKnown;
                }

                this.glBaseInternalFormatAsUint = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();
                if (GlPixelFormat.IsDefined(typeof(GlPixelFormat), this.glBaseInternalFormatAsUint))
                {
                    this.glPixelFormat = (GlPixelFormat)this.glBaseInternalFormatAsUint;
                }
                else
                {
                    this.glPixelFormat = GlPixelFormat.NotKnown;
                }

                this.pixelWidth = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.pixelHeight = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.pixelDepth = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.numberOfArrayElements = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.numberOfFaces = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.numberOfMipmapLevels = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                this.bytesOfKeyValueData = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                // Check that bytesOfKeyValueData is mod 4
                if (this.bytesOfKeyValueData % 4 != 0)
                {
                    throw new InvalidOperationException(ErrorGen.Modulo4Error(nameof(this.bytesOfKeyValueData), this.bytesOfKeyValueData));
                }

                this.metadataDictionary = ParseMetadata(reader.ReadBytes((int)this.bytesOfKeyValueData), shouldSwapEndianness);
            }
        }