Exemplo n.º 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);
            }
        }
Exemplo n.º 2
0
        public static (bool isValid, string possibleError) ValidateHeaderData(MemoryStream memoryStream)
        {
            // Use the memory stream in a binary reader.
            try
            {
                using (BinaryReader reader = new BinaryReader(memoryStream, Encoding.UTF8, leaveOpen: true))
                {
                    // Start validating header
                    byte[] tempIdentifier = reader.ReadBytes(Common.onlyValidIdentifier.Length);

                    if (!Common.onlyValidIdentifier.SequenceEqual(tempIdentifier))
                    {
                        return(isValid : false, possibleError : "Identifier does not match requirements!");
                    }

                    uint tempEndian = reader.ReadUInt32();

                    if (Common.expectedEndianValue != tempEndian && Common.otherValidEndianValue != tempEndian)
                    {
                        return(isValid : false, possibleError : "Endianness does not match requirements!");
                    }

                    bool shouldSwapEndianness = (tempEndian != Common.expectedEndianValue);

                    uint glTypeTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();
                    // TODO: uint glType to enum

                    // If glType is 0 it should mean that this is compressed texture
                    bool assumeCompressedTexture = (glTypeTemp == 0);

                    uint glTypeSizeTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    if (assumeCompressedTexture && glTypeSizeTemp != 1)
                    {
                        return(isValid : false, possibleError : "glTypeSize should be 1 for compressed textures!");
                    }

                    uint glFormatTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    if (assumeCompressedTexture && glFormatTemp != 0)
                    {
                        return(isValid : false, possibleError : "glFormat should be 0 for compressed textures!");
                    }

                    uint glInternalFormatTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint glBaseInternalFormatTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint pixelWidthTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint pixelHeightTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint pixelDepthTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint numberOfArrayElementsTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint numberOfFacesTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint numberOfMipmapLevelsTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();

                    uint sizeOfKeyValueDataTemp = shouldSwapEndianness ? KtxBitFiddling.SwapEndian(reader.ReadUInt32()) : reader.ReadUInt32();
                    if (sizeOfKeyValueDataTemp % 4 != 0)
                    {
                        return(isValid : false, possibleError : ErrorGen.Modulo4Error(nameof(sizeOfKeyValueDataTemp), sizeOfKeyValueDataTemp));
                    }

                    // Validate metadata
                    (bool validMedata, string possibleMetadataError) = ValidateMetadata(reader, sizeOfKeyValueDataTemp, shouldSwapEndianness);
                    if (!validMedata)
                    {
                        return(isValid : false, possibleError : possibleMetadataError);
                    }
                }
            }
            catch (Exception e)
            {
                return(isValid : false, e.ToString());
            }

            return(isValid : true, possibleError : "");
        }