Exemplo n.º 1
0
        /// <summary>Processes a RIFF data sequence.</summary>
        /// <param name="reader">The <see cref="SequentialReader"/> from which the data should be read.</param>
        /// <param name="handler">The <see cref="IRiffHandler"/> that will coordinate processing and accept read values.</param>
        /// <exception cref="RiffProcessingException">An error occurred during the processing of RIFF data that could not be ignored or recovered from.</exception>
        /// <exception cref="System.IO.IOException">an error occurred while accessing the required data</exception>
        public void ProcessRiff([NotNull] SequentialReader reader, [NotNull] IRiffHandler handler)
        {
            // RIFF files are always little-endian
            reader = reader.WithByteOrder(isMotorolaByteOrder: false);

            // PROCESS FILE HEADER

            var fileFourCc = reader.GetString(4, Encoding.ASCII);

            if (fileFourCc != "RIFF")
            {
                throw new RiffProcessingException("Invalid RIFF header: " + fileFourCc);
            }

            // The total size of the chunks that follow plus 4 bytes for the 'WEBP' or 'AVI ' FourCC
            int    fileSize   = reader.GetInt32();
            int    sizeLeft   = fileSize;
            string identifier = reader.GetString(4, Encoding.ASCII);

            sizeLeft -= 4;

            if (!handler.ShouldAcceptRiffIdentifier(identifier))
            {
                return;
            }

            ProcessChunks(reader, sizeLeft, handler);
        }
Exemplo n.º 2
0
        /// <summary>Processes a RIFF data sequence.</summary>
        /// <param name="reader">The <see cref="SequentialReader"/> from which the data should be read.</param>
        /// <param name="handler">The <see cref="IRiffHandler"/> that will coordinate processing and accept read values.</param>
        /// <exception cref="RiffProcessingException">An error occurred during the processing of RIFF data that could not be ignored or recovered from.</exception>
        /// <exception cref="System.IO.IOException">an error occurred while accessing the required data</exception>
        public void ProcessRiff([NotNull] SequentialReader reader, [NotNull] IRiffHandler handler)
        {
            // RIFF files are always little-endian
            reader = reader.WithByteOrder(isMotorolaByteOrder: false);

            // PROCESS FILE HEADER

            var fileFourCc = reader.GetString(4, Encoding.UTF8);

            if (fileFourCc != "RIFF")
            {
                throw new RiffProcessingException("Invalid RIFF header: " + fileFourCc);
            }

            // The total size of the chunks that follow plus 4 bytes for the 'WEBP' FourCC
            var fileSize   = reader.GetInt32();
            var sizeLeft   = fileSize;
            var identifier = reader.GetString(4, Encoding.UTF8);

            sizeLeft -= 4;

            if (!handler.ShouldAcceptRiffIdentifier(identifier))
            {
                return;
            }

            // PROCESS CHUNKS

            while (sizeLeft != 0)
            {
                var chunkFourCc = reader.GetString(4, Encoding.UTF8);
                var chunkSize   = reader.GetInt32();

                sizeLeft -= 8;

                // NOTE we fail a negative chunk size here (greater than 0x7FFFFFFF) as we cannot allocate arrays larger than this
                if (chunkSize < 0 || sizeLeft < chunkSize)
                {
                    throw new RiffProcessingException("Invalid RIFF chunk size");
                }

                if (handler.ShouldAcceptChunk(chunkFourCc))
                {
                    // TODO is it feasible to avoid copying the chunk here, and to pass the sequential reader to the handler?
                    handler.ProcessChunk(chunkFourCc, reader.GetBytes(chunkSize));
                }
                else
                {
                    reader.Skip(chunkSize);
                }

                sizeLeft -= chunkSize;

                // Skip any padding byte added to keep chunks aligned to even numbers of bytes
                if (chunkSize % 2 == 1)
                {
                    reader.GetSByte();
                    sizeLeft--;
                }
            }
        }