/// <summary>
        /// Load quantization and/or Huffman tables for subsequent use for jpeg's embedded in tiff's,
        /// so those tables do not need to be duplicated with segmented tiff's (tiff's with multiple strips).
        /// </summary>
        /// <param name="tableBytes">The table bytes.</param>
        /// <param name="huffmanScanDecoder">The scan decoder.</param>
        public void LoadTables(byte[] tableBytes, HuffmanScanDecoder huffmanScanDecoder)
        {
            this.Metadata = new ImageMetadata();
            this.QuantizationTables = new Block8x8F[4];
            this.scanDecoder = huffmanScanDecoder;
            using var ms = new MemoryStream(tableBytes);
            using var stream = new BufferedReadStream(this.Configuration, ms);

            // Check for the Start Of Image marker.
            stream.Read(this.markerBuffer, 0, 2);
            var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
            if (fileMarker.Marker != JpegConstants.Markers.SOI)
            {
                JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker.");
            }

            // Read next marker.
            stream.Read(this.markerBuffer, 0, 2);
            byte marker = this.markerBuffer[1];
            fileMarker = new JpegFileMarker(marker, (int)stream.Position - 2);

            while (fileMarker.Marker != JpegConstants.Markers.EOI || (fileMarker.Marker == JpegConstants.Markers.EOI && fileMarker.Invalid))
            {
                if (!fileMarker.Invalid)
                {
                    // Get the marker length.
                    int remaining = this.ReadUint16(stream) - 2;

                    switch (fileMarker.Marker)
                    {
                        case JpegConstants.Markers.SOI:
                            break;
                        case JpegConstants.Markers.RST0:
                        case JpegConstants.Markers.RST7:
                            break;
                        case JpegConstants.Markers.DHT:
                            this.ProcessDefineHuffmanTablesMarker(stream, remaining);
                            break;
                        case JpegConstants.Markers.DQT:
                            this.ProcessDefineQuantizationTablesMarker(stream, remaining);
                            break;
                        case JpegConstants.Markers.DRI:
                            this.ProcessDefineRestartIntervalMarker(stream, remaining);
                            break;
                        case JpegConstants.Markers.EOI:
                            return;
                    }
                }

                // Read next marker.
                stream.Read(this.markerBuffer, 0, 2);
                fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
            }
        }
Exemplo n.º 2
0
    public override int Read(byte[] buffer, int offset, int count)
    {
        if (_finished)
        {
            return(0);
        }

        PositionInnerStream();
        if (!_innerStream.EnsureBuffered(_boundary.FinalBoundaryLength))
        {
            throw new IOException("Unexpected end of Stream, the content may have already been read by another component. ");
        }
        var bufferedData = _innerStream.BufferedData;

        // scan for a boundary match, full or partial.
        int read;

        if (SubMatch(bufferedData, _boundary.BoundaryBytes, out var matchOffset, out var matchCount))
        {
            // We found a possible match, return any data before it.
            if (matchOffset > bufferedData.Offset)
            {
                read = _innerStream.Read(buffer, offset, Math.Min(count, matchOffset - bufferedData.Offset));
                return(UpdatePosition(read));
            }

            var length = _boundary.BoundaryBytes.Length;
            Debug.Assert(matchCount == length);

            // "The boundary may be followed by zero or more characters of
            // linear whitespace. It is then terminated by either another CRLF"
            // or -- for the final boundary.
            var boundary = _bytePool.Rent(length);
            read = _innerStream.Read(boundary, 0, length);
            _bytePool.Return(boundary);
            Debug.Assert(read == length);                            // It should have all been buffered

            var remainder = _innerStream.ReadLine(lengthLimit: 100); // Whitespace may exceed the buffer.
            remainder = remainder.Trim();
            if (string.Equals("--", remainder, StringComparison.Ordinal))
            {
                FinalBoundaryFound = true;
            }
            Debug.Assert(FinalBoundaryFound || string.Equals(string.Empty, remainder, StringComparison.Ordinal), "Un-expected data found on the boundary line: " + remainder);
            _finished = true;
            return(0);
        }

        // No possible boundary match within the buffered data, return the data from the buffer.
        read = _innerStream.Read(buffer, offset, Math.Min(count, bufferedData.Count));
        return(UpdatePosition(read));
    }
        /// <summary>
        /// Finds the next file marker within the byte stream.
        /// </summary>
        /// <param name="marker">The buffer to read file markers to.</param>
        /// <param name="stream">The input stream.</param>
        /// <returns>The <see cref="JpegFileMarker"/></returns>
        public static JpegFileMarker FindNextFileMarker(byte[] marker, BufferedReadStream stream)
        {
            int value = stream.Read(marker, 0, 2);

            if (value == 0)
            {
                return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
            }

            if (marker[0] == JpegConstants.Markers.XFF)
            {
                // According to Section B.1.1.2:
                // "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code 0xFF."
                int m = marker[1];
                while (m == JpegConstants.Markers.XFF)
                {
                    int suffix = stream.ReadByte();
                    if (suffix == -1)
                    {
                        return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
                    }

                    m = suffix;
                }

                return new JpegFileMarker((byte)m, stream.Position - 2);
            }

            return new JpegFileMarker(marker[1], stream.Position - 2, true);
        }
        public void BufferedStreamCanReadSubsequentMultipleByteSpanCorrectly()
        {
            using (MemoryStream stream = this.CreateTestStream())
            {
                Span <byte> buffer   = new byte[2];
                byte[]      expected = stream.ToArray();
                using (var reader = new BufferedReadStream(stream))
                {
                    for (int i = 0, o = 0; i < expected.Length / 2; i++, o += 2)
                    {
                        Assert.Equal(2, reader.Read(buffer, 0, 2));
                        Assert.Equal(expected[o], buffer[0]);
                        Assert.Equal(expected[o + 1], buffer[1]);
                        Assert.Equal(o + 2, reader.Position);

                        int offset = i * 2;
                        if (offset < BufferedReadStream.BufferLength)
                        {
                            Assert.Equal(stream.Position, BufferedReadStream.BufferLength);
                        }
                        else if (offset >= BufferedReadStream.BufferLength && offset < BufferedReadStream.BufferLength * 2)
                        {
                            // We should have advanced to the second chunk now.
                            Assert.Equal(stream.Position, BufferedReadStream.BufferLength * 2);
                        }
                        else
                        {
                            // We should have advanced to the third chunk now.
                            Assert.Equal(stream.Position, BufferedReadStream.BufferLength * 3);
                        }
                    }
                }
            }
        }
        /// <inheritdoc/>
        protected override void Decompress(BufferedReadStream stream, int byteCount, int stripHeight, Span <byte> buffer)
        {
            if (this.compressedDataMemory == null)
            {
                this.compressedDataMemory = this.Allocator.Allocate <byte>(byteCount);
            }
            else if (this.compressedDataMemory.Length() < byteCount)
            {
                this.compressedDataMemory.Dispose();
                this.compressedDataMemory = this.Allocator.Allocate <byte>(byteCount);
            }

            Span <byte> compressedData = this.compressedDataMemory.GetSpan();

            stream.Read(compressedData, 0, byteCount);
            int compressedOffset   = 0;
            int decompressedOffset = 0;

            while (compressedOffset < byteCount)
            {
                byte headerByte = compressedData[compressedOffset];

                if (headerByte <= 127)
                {
                    int literalOffset = compressedOffset + 1;
                    int literalLength = compressedData[compressedOffset] + 1;

                    if ((literalOffset + literalLength) > compressedData.Length)
                    {
                        TiffThrowHelper.ThrowImageFormatException("Tiff packbits compression error: not enough data.");
                    }

                    compressedData.Slice(literalOffset, literalLength).CopyTo(buffer.Slice(decompressedOffset));

                    compressedOffset   += literalLength + 1;
                    decompressedOffset += literalLength;
                }
                else if (headerByte == 0x80)
                {
                    compressedOffset += 1;
                }
                else
                {
                    byte repeatData   = compressedData[compressedOffset + 1];
                    int  repeatLength = 257 - headerByte;

                    ArrayCopyRepeat(repeatData, buffer, decompressedOffset, repeatLength);

                    compressedOffset   += 2;
                    decompressedOffset += repeatLength;
                }
            }
        }
Exemplo n.º 6
0
        public int BufferedReadStreamRead()
        {
            int r = 0;
            BufferedReadStream reader = this.bufferedStream1;

            byte[] b = this.chunk2;

            for (int i = 0; i < reader.Length / 2; i++)
            {
                r += reader.Read(b, 0, 2);
            }

            return(r);
        }
        public void BufferedStreamCanReadSubsequentMultipleByteSpanCorrectly(int bufferSize)
        {
            this.configuration.StreamProcessingBufferSize = bufferSize;
            using (MemoryStream stream = this.CreateTestStream(bufferSize * 3))
            {
                const int   increment = 2;
                Span <byte> buffer    = new byte[2];
                byte[]      expected  = stream.ToArray();
                using (var reader = new BufferedReadStream(this.configuration, stream))
                {
                    for (int i = 0, o = 0; i < expected.Length / increment; i++, o += increment)
                    {
                        // Check values are correct.
                        Assert.Equal(increment, reader.Read(buffer, 0, increment));
                        Assert.Equal(expected[o], buffer[0]);
                        Assert.Equal(expected[o + 1], buffer[1]);
                        Assert.Equal(o + increment, reader.Position);

                        // These tests ensure that we are correctly reading
                        // our buffer in chunks of the given size.
                        int offset = i * increment;

                        // First chunk.
                        if (offset < bufferSize)
                        {
                            // We've read an entire chunk once and are
                            // now reading from that chunk.
                            Assert.True(stream.Position >= bufferSize);
                            continue;
                        }

                        // Second chunk
                        if (offset < bufferSize * 2)
                        {
                            Assert.True(stream.Position > bufferSize);

                            // Odd buffer size with even increments can
                            // jump to the third chunk on final read.
                            Assert.True(stream.Position <= bufferSize * 3);
                            continue;
                        }

                        // Third chunk
                        Assert.True(stream.Position > bufferSize * 2);
                    }
                }
            }
        }
        public void BufferedStreamCanReadMultipleBytesFromOrigin()
        {
            using (MemoryStream stream = this.CreateTestStream())
            {
                var    buffer   = new byte[2];
                byte[] expected = stream.ToArray();
                using (var reader = new BufferedReadStream(stream))
                {
                    Assert.Equal(2, reader.Read(buffer, 0, 2));
                    Assert.Equal(expected[0], buffer[0]);
                    Assert.Equal(expected[1], buffer[1]);

                    // We've read a whole chunk but increment by the buffer length in our reader.
                    Assert.Equal(stream.Position, BufferedReadStream.BufferLength);
                    Assert.Equal(buffer.Length, reader.Position);
                }
            }
        }
        public void BufferedStreamCanReadMultipleBytesFromOrigin(int bufferSize)
        {
            this.configuration.StreamProcessingBufferSize = bufferSize;
            using (MemoryStream stream = this.CreateTestStream(bufferSize * 3))
            {
                var    buffer   = new byte[2];
                byte[] expected = stream.ToArray();
                using (var reader = new BufferedReadStream(this.configuration, stream))
                {
                    Assert.Equal(2, reader.Read(buffer, 0, 2));
                    Assert.Equal(expected[0], buffer[0]);
                    Assert.Equal(expected[1], buffer[1]);

                    // We've read a whole chunk but increment by the buffer length in our reader.
                    Assert.True(stream.Position >= bufferSize);
                    Assert.Equal(buffer.Length, reader.Position);
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Parses the input stream for file markers.
        /// </summary>
        /// <param name="stream">The input stream.</param>
        /// <param name="scanDecoder">Scan decoder used exclusively to decode SOS marker.</param>
        /// <param name="cancellationToken">The token to monitor cancellation.</param>
        internal void ParseStream(BufferedReadStream stream, HuffmanScanDecoder scanDecoder, CancellationToken cancellationToken)
        {
            bool metadataOnly = scanDecoder == null;

            this.scanDecoder = scanDecoder;

            this.Metadata = new ImageMetadata();

            // Check for the Start Of Image marker.
            stream.Read(this.markerBuffer, 0, 2);
            var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
            if (fileMarker.Marker != JpegConstants.Markers.SOI)
            {
                JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker.");
            }

            stream.Read(this.markerBuffer, 0, 2);
            byte marker = this.markerBuffer[1];
            fileMarker = new JpegFileMarker(marker, (int)stream.Position - 2);
            this.QuantizationTables ??= new Block8x8F[4];

            // Break only when we discover a valid EOI marker.
            // https://github.com/SixLabors/ImageSharp/issues/695
            while (fileMarker.Marker != JpegConstants.Markers.EOI
                || (fileMarker.Marker == JpegConstants.Markers.EOI && fileMarker.Invalid))
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (!fileMarker.Invalid)
                {
                    // Get the marker length.
                    int remaining = this.ReadUint16(stream) - 2;

                    switch (fileMarker.Marker)
                    {
                        case JpegConstants.Markers.SOF0:
                        case JpegConstants.Markers.SOF1:
                        case JpegConstants.Markers.SOF2:
                            this.ProcessStartOfFrameMarker(stream, remaining, fileMarker, metadataOnly);
                            break;

                        case JpegConstants.Markers.SOF5:
                            JpegThrowHelper.ThrowNotSupportedException("Decoding jpeg files with differential sequential DCT is not supported.");
                            break;

                        case JpegConstants.Markers.SOF6:
                            JpegThrowHelper.ThrowNotSupportedException("Decoding jpeg files with differential progressive DCT is not supported.");
                            break;

                        case JpegConstants.Markers.SOF3:
                        case JpegConstants.Markers.SOF7:
                            JpegThrowHelper.ThrowNotSupportedException("Decoding lossless jpeg files is not supported.");
                            break;

                        case JpegConstants.Markers.SOF9:
                        case JpegConstants.Markers.SOF10:
                        case JpegConstants.Markers.SOF11:
                        case JpegConstants.Markers.SOF13:
                        case JpegConstants.Markers.SOF14:
                        case JpegConstants.Markers.SOF15:
                            JpegThrowHelper.ThrowNotSupportedException("Decoding jpeg files with arithmetic coding is not supported.");
                            break;

                        case JpegConstants.Markers.SOS:
                            if (!metadataOnly)
                            {
                                this.ProcessStartOfScanMarker(stream, remaining);
                                break;
                            }
                            else
                            {
                                // It's highly unlikely that APPn related data will be found after the SOS marker
                                // We should have gathered everything we need by now.
                                return;
                            }

                        case JpegConstants.Markers.DHT:

                            if (metadataOnly)
                            {
                                stream.Skip(remaining);
                            }
                            else
                            {
                                this.ProcessDefineHuffmanTablesMarker(stream, remaining);
                            }

                            break;

                        case JpegConstants.Markers.DQT:
                            this.ProcessDefineQuantizationTablesMarker(stream, remaining);
                            break;

                        case JpegConstants.Markers.DRI:
                            if (metadataOnly)
                            {
                                stream.Skip(remaining);
                            }
                            else
                            {
                                this.ProcessDefineRestartIntervalMarker(stream, remaining);
                            }

                            break;

                        case JpegConstants.Markers.APP0:
                            this.ProcessApplicationHeaderMarker(stream, remaining);
                            break;

                        case JpegConstants.Markers.APP1:
                            this.ProcessApp1Marker(stream, remaining);
                            break;

                        case JpegConstants.Markers.APP2:
                            this.ProcessApp2Marker(stream, remaining);
                            break;

                        case JpegConstants.Markers.APP3:
                        case JpegConstants.Markers.APP4:
                        case JpegConstants.Markers.APP5:
                        case JpegConstants.Markers.APP6:
                        case JpegConstants.Markers.APP7:
                        case JpegConstants.Markers.APP8:
                        case JpegConstants.Markers.APP9:
                        case JpegConstants.Markers.APP10:
                        case JpegConstants.Markers.APP11:
                        case JpegConstants.Markers.APP12:
                            stream.Skip(remaining);
                            break;

                        case JpegConstants.Markers.APP13:
                            this.ProcessApp13Marker(stream, remaining);
                            break;

                        case JpegConstants.Markers.APP14:
                            this.ProcessApp14Marker(stream, remaining);
                            break;

                        case JpegConstants.Markers.APP15:
                        case JpegConstants.Markers.COM:
                            stream.Skip(remaining);
                            break;

                        case JpegConstants.Markers.DAC:
                            JpegThrowHelper.ThrowNotSupportedException("Decoding jpeg files with arithmetic coding is not supported.");
                            break;
                    }
                }

                // Read on.
                fileMarker = FindNextFileMarker(this.markerBuffer, stream);
            }
        }
Exemplo n.º 11
0
        PageHeader ReadPageHeader(long position)
        {
            // set the stream's position
            _stream.Seek(position, SeekOrigin.Begin);

            // header
            // NB: if the stream didn't have an EOS flag, this is the most likely spot for the EOF to be found...
            if (_stream.Read(_readBuffer, 0, 27) != 27)
            {
                return(null);
            }

            // capture signature
            if (_readBuffer[0] != 0x4f || _readBuffer[1] != 0x67 || _readBuffer[2] != 0x67 || _readBuffer[3] != 0x53)
            {
                return(null);
            }

            // check the stream version
            if (_readBuffer[4] != 0)
            {
                return(null);
            }

            // start populating the header
            var hdr = new PageHeader();

            // bit flags
            hdr.Flags = (PageFlags)_readBuffer[5];

            // granulePosition
            hdr.GranulePosition = BitConverter.ToInt64(_readBuffer, 6);

            // stream serial
            hdr.StreamSerial = BitConverter.ToInt32(_readBuffer, 14);

            // sequence number
            hdr.SequenceNumber = BitConverter.ToInt32(_readBuffer, 18);

            // save off the CRC
            var crc = BitConverter.ToUInt32(_readBuffer, 22);

            // start calculating the CRC value for this page
            _crc.Reset();
            for (int i = 0; i < 22; i++)
            {
                _crc.Update(_readBuffer[i]);
            }
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(_readBuffer[26]);

            // figure out the length of the page
            var segCnt = (int)_readBuffer[26];

            if (_stream.Read(_readBuffer, 0, segCnt) != segCnt)
            {
                return(null);
            }

            var packetSizes = new List <int>(segCnt);

            int size = 0, idx = 0;

            for (int i = 0; i < segCnt; i++)
            {
                var temp = _readBuffer[i];
                _crc.Update(temp);

                if (idx == packetSizes.Count)
                {
                    packetSizes.Add(0);
                }
                packetSizes[idx] += temp;
                if (temp < 255)
                {
                    ++idx;
                    hdr.LastPacketContinues = false;
                }
                else
                {
                    hdr.LastPacketContinues = true;
                }

                size += temp;
            }
            hdr.PacketSizes = packetSizes.ToArray();
            hdr.DataOffset  = position + 27 + segCnt;

            // now we have to go through every byte in the page
            if (_stream.Read(_readBuffer, 0, size) != size)
            {
                return(null);
            }
            for (int i = 0; i < size; i++)
            {
                _crc.Update(_readBuffer[i]);
            }

            if (_crc.Test(crc))
            {
                _containerBits += 8 * (27 + segCnt);
                ++_pageCount;
                return(hdr);
            }
            return(null);
        }
Exemplo n.º 12
0
        public PageHeader ReadPageHeader(long position)
        {
            _stream.Seek(position, SeekOrigin.Begin);
            if (_stream.Read(_readBuffer, 0, 27) != 27)
            {
                return(null);
            }
            if (_readBuffer[0] != 79 || _readBuffer[1] != 103 || _readBuffer[2] != 103 || _readBuffer[3] != 83)
            {
                return(null);
            }
            if (_readBuffer[4] != 0)
            {
                return(null);
            }
            PageHeader pageHeader = new PageHeader();

            pageHeader.Flags = (PageFlags)_readBuffer[5];
            long num  = BitConverter.ToInt32(_readBuffer, 6);
            long num2 = BitConverter.ToInt32(_readBuffer, 10);

            pageHeader.GranulePosition = num + (num2 << 32);
            pageHeader.StreamSerial    = BitConverter.ToInt32(_readBuffer, 14);
            pageHeader.SequenceNumber  = BitConverter.ToInt32(_readBuffer, 18);
            uint checkCrc = BitConverter.ToUInt32(_readBuffer, 22);

            _crc.Reset();
            for (int i = 0; i < 22; i++)
            {
                _crc.Update(_readBuffer[i]);
            }
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(_readBuffer[26]);
            int num3 = _readBuffer[26];

            if (_stream.Read(_readBuffer, 0, num3) != num3)
            {
                return(null);
            }
            List <int> list = new List <int>(num3);
            int        num4 = 0;
            int        num5 = 0;

            for (int j = 0; j < num3; j++)
            {
                byte b = _readBuffer[j];
                _crc.Update(b);
                if (num5 == list.Count)
                {
                    list.Add(0);
                }
                list[num5] += b;
                if (b < byte.MaxValue)
                {
                    num5++;
                    pageHeader.LastPacketContinues = false;
                }
                else
                {
                    pageHeader.LastPacketContinues = true;
                }
                num4 += b;
            }
            pageHeader.PacketSizes = list.ToArray();
            pageHeader.DataOffset  = position + 27 + num3;
            if (_stream.Read(_readBuffer, 0, num4) != num4)
            {
                return(null);
            }
            for (int k = 0; k < num4; k++)
            {
                _crc.Update(_readBuffer[k]);
            }
            if (_crc.Test(checkCrc))
            {
                _containerBits += 8 * (27 + num3);
                _pageCount++;
                return(pageHeader);
            }
            return(null);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Parses the input stream for file markers
        /// </summary>
        /// <param name="stream">The input stream</param>
        /// <param name="metadataOnly">Whether to decode metadata only.</param>
        /// <param name="cancellationToken">The token to monitor cancellation.</param>
        public void ParseStream(BufferedReadStream stream, bool metadataOnly = false, CancellationToken cancellationToken = default)
        {
            this.Metadata = new ImageMetadata();

            // Check for the Start Of Image marker.
            stream.Read(this.markerBuffer, 0, 2);
            var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);

            if (fileMarker.Marker != JpegConstants.Markers.SOI)
            {
                JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker.");
            }

            stream.Read(this.markerBuffer, 0, 2);
            byte marker = this.markerBuffer[1];

            fileMarker = new JpegFileMarker(marker, (int)stream.Position - 2);
            this.QuantizationTables = new Block8x8F[4];

            // Only assign what we need
            if (!metadataOnly)
            {
                const int maxTables = 4;
                this.dcHuffmanTables = new HuffmanTable[maxTables];
                this.acHuffmanTables = new HuffmanTable[maxTables];
            }

            // Break only when we discover a valid EOI marker.
            // https://github.com/SixLabors/ImageSharp/issues/695
            while (fileMarker.Marker != JpegConstants.Markers.EOI ||
                   (fileMarker.Marker == JpegConstants.Markers.EOI && fileMarker.Invalid))
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (!fileMarker.Invalid)
                {
                    // Get the marker length
                    int remaining = this.ReadUint16(stream) - 2;

                    switch (fileMarker.Marker)
                    {
                    case JpegConstants.Markers.SOF0:
                    case JpegConstants.Markers.SOF1:
                    case JpegConstants.Markers.SOF2:
                        this.ProcessStartOfFrameMarker(stream, remaining, fileMarker, metadataOnly);
                        break;

                    case JpegConstants.Markers.SOS:
                        if (!metadataOnly)
                        {
                            this.ProcessStartOfScanMarker(stream, cancellationToken);
                            break;
                        }
                        else
                        {
                            // It's highly unlikely that APPn related data will be found after the SOS marker
                            // We should have gathered everything we need by now.
                            return;
                        }

                    case JpegConstants.Markers.DHT:

                        if (metadataOnly)
                        {
                            stream.Skip(remaining);
                        }
                        else
                        {
                            this.ProcessDefineHuffmanTablesMarker(stream, remaining);
                        }

                        break;

                    case JpegConstants.Markers.DQT:
                        this.ProcessDefineQuantizationTablesMarker(stream, remaining);
                        break;

                    case JpegConstants.Markers.DRI:
                        if (metadataOnly)
                        {
                            stream.Skip(remaining);
                        }
                        else
                        {
                            this.ProcessDefineRestartIntervalMarker(stream, remaining);
                        }

                        break;

                    case JpegConstants.Markers.APP0:
                        this.ProcessApplicationHeaderMarker(stream, remaining);
                        break;

                    case JpegConstants.Markers.APP1:
                        this.ProcessApp1Marker(stream, remaining);
                        break;

                    case JpegConstants.Markers.APP2:
                        this.ProcessApp2Marker(stream, remaining);
                        break;

                    case JpegConstants.Markers.APP3:
                    case JpegConstants.Markers.APP4:
                    case JpegConstants.Markers.APP5:
                    case JpegConstants.Markers.APP6:
                    case JpegConstants.Markers.APP7:
                    case JpegConstants.Markers.APP8:
                    case JpegConstants.Markers.APP9:
                    case JpegConstants.Markers.APP10:
                    case JpegConstants.Markers.APP11:
                    case JpegConstants.Markers.APP12:
                        stream.Skip(remaining);
                        break;

                    case JpegConstants.Markers.APP13:
                        this.ProcessApp13Marker(stream, remaining);
                        break;

                    case JpegConstants.Markers.APP14:
                        this.ProcessApp14Marker(stream, remaining);
                        break;

                    case JpegConstants.Markers.APP15:
                    case JpegConstants.Markers.COM:
                        stream.Skip(remaining);
                        break;
                    }
                }

                // Read on.
                fileMarker = FindNextFileMarker(this.markerBuffer, stream);
            }
        }
Exemplo n.º 14
0
        private unsafe bool ReadPageHeader(long position, out PageHeader header)
        {
            header = default;

            // set the stream's position
            _stream.Seek(position, SeekOrigin.Begin);

            // header
            // NB: if the stream didn't have an EOS flag, this is the most likely spot for the EOF to be found...
            if (_stream.Read(_readBuffer, 0, 27) != 27)
            {
                return(false);
            }

            // capture signature
            if (_readBuffer[0] != 0x4f || _readBuffer[1] != 0x67 || _readBuffer[2] != 0x67 || _readBuffer[3] != 0x53)
            {
                return(false);
            }

            // check the stream version
            if (_readBuffer[4] != 0)
            {
                return(false);
            }

            // start populating the header
            header = new PageHeader();

            // bit flags
            header.Flags = (OggPageFlags)_readBuffer[5];

            // granulePosition
            header.GranulePosition = BitConverter.ToInt64(_readBuffer, 6);

            // stream serial
            header.StreamSerial = BitConverter.ToInt32(_readBuffer, 14);

            // sequence number
            header.SequenceNumber = BitConverter.ToInt32(_readBuffer, 18);

            // save off the CRC
            var crc = BitConverter.ToUInt32(_readBuffer, 22);

            // start calculating the CRC value for this page
            _crc.Reset();
            for (int i = 0; i < 22; i++)
            {
                _crc.Update(_readBuffer[i]);
            }

            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(0);
            _crc.Update(_readBuffer[26]);

            // figure out the length of the page
            header.SegCount = _readBuffer[26];
            if (_stream.Read(_readBuffer, 0, header.SegCount) != header.SegCount)
            {
                return(false);
            }

            int size = 0;
            int idx  = 0;

            for (int i = 0; i < header.SegCount; i++)
            {
                var tmp = _readBuffer[i];
                _crc.Update(tmp);

                header.PacketSizes[idx] += tmp;

                if (tmp < 255)
                {
                    idx++;
                    header.LastPacketContinues = false;
                }
                else
                {
                    header.LastPacketContinues = true;
                }

                size += tmp;
            }
            header.DataOffset = position + 27 + header.SegCount;

            // now we have to go through every byte in the page
            if (_stream.Read(_readBuffer, 0, size) != size)
            {
                return(false);
            }

            for (int i = 0; i < size; i++)
            {
                _crc.Update(_readBuffer[i]);
            }

            if (_crc.Test(crc))
            {
                _containerBits += 8 * (27 + header.SegCount);
                ++_pageCount;
                return(true);
            }
            return(false);
        }
Exemplo n.º 15
0
 /// <inheritdoc/>
 protected override void Decompress(BufferedReadStream stream, int byteCount, int stripHeight, Span <byte> buffer)
 => _ = stream.Read(buffer, 0, Math.Min(buffer.Length, byteCount));